Java核心卷(I)学习笔记(2)

前言:

     前面记录了学习完Java核心卷,类与对象这一章后的一些体会和理解,接下来我会接着记录学习继承这一章节的心得。不足之处请多多指教。

1.类、超类和子类

     前一个笔记中的Employee类,可以得出一个职工的薪水,但在现实生活中我们会发现一个公司中,并不只有普通员工还有经理等等一些特殊雇员。他们之间虽然存在差异,但他们都领薪水,不同的是,普通员工完成任务后可领取薪水,但经理完成任务后不仅可以领取薪水还可以领取奖金。

     这时候就可以利用继承解决这一问题,通过extends关键字为经理定义一个继承于Employee类的新类Manager,Manager可以重用Employee类中编写的部分代码,并将其所有域保留下来。

格式:

class Manager extends Employee

{

添加方法和域

}

    extends表明构造的新类派生于一个已存在的类,通常将已存在的类称为父类,派生的类称为子类。一般子类的功能多于父类的功能,就像刚刚的 Manager类它所封装的信息就多余Employee类封装的数据。

package Exemple;
public class Manager extends Employee{
    private double bonus; //奖金
    public Manager(String n,double s, int year,int month, int day)
    {
        super(n,s,year,month,day);
        bonus = 0;
    }
    public double getSalary()
    {
        double baseSalary = super.getSalary();
        return baseSalary+bonus; //计算总薪水
    }
    public void setBonus(double b)
    {
        bonus = b;
    }
}

通过代码,我们可以看到Manager类中并没有显式定义getName和getHireDay方法,也并没有定义name、salary等域,但是Manager的对象却可以使用它们,这是因为Manager自动继承了父类中的方法和域。也就是每个Manager的对象都包含了name、salary、hireDay和bonus这四个域。

     在代码中我们使用了super,原因是我们想要使用是父类中的getSalary方法,super与this不同它不是一个对象的引用,不能将super赋给另一个对象变量,它只是一个指示编译器调用父类方法的特有关键字。

     在构造器中:

public Manager(String n, double s, int year, int month, int day)

{

super(n,s,year,month,day)

bonus = b;

}

这里也使用了super,但这里的含义确实,调用Employee类中含有:n,s,year,month,day参数的构造器。

super关键字的用途:

    1.调用父类的方法。2.调用父类的构造器。在调用构造器时super和this类似。调用构造器的语句只能作为另一个构造器的第一条语句出现。构造器参数既能传递给本类(this)的其它构造器,也可以传递父类(super)的构造器。完整代码:

package Exemple;

public class EmployeeTest {
    public static void main(String[] args) {

        Manager boss = new Manager("Tom",8000,1977,12,15);
        boss.setBonus(5000);

        Employee[] staff = new Employee[3];

        staff[0] = boss;
        staff[1] = new Employee("Carl Cracker1",65000,1989,10,11);
        staff[2] = new Employee("Carl Cracker2",78000,1977,2,15);
        for(Employee e:staff)
            e.raiseSalary(5);

        for(Employee e:staff)
            System.out.println("name=" + e.getName() + ",salary=" + e.getSalary() + ",hirDay=" + e.getHireDay());
    }
}

package Exemple;
public class Manager extends Employee{
    private double bonus;
    public Manager(String n,double s, int year,int month, int day)
    {
        super(n,s,year,month,day);
        bonus = 0;
    }
    public double getSalary()
    {
        double baseSalary = super.getSalary();
        return baseSalary+bonus;
    }
    public void setBonus(double b)
    {
        bonus = b;
    }
}
package Exemple;
import java.util.*;
public class Employee {
    private String name;
    private double salary;
    private Date hireDay;
    public Employee(String n, double s, int year, int month, int day)
    {
        name = n;
        salary = s;
        GregorianCalendar calendar = new GregorianCalendar(year,month - 1,day);
        hireDay = calendar.getTime();
    }
    public String getName()
    {
        return name;
    }
    public double getSalary()
    {
        return salary;
    }
    public Date getHireDay()
    {
        return hireDay;
    }
//    public void raiseSalary(double byPercent)
//    {
//        double raise = salary * byPercent / 100;
//        salary += raise;
//    }
    public void raiseSalary(double byPercent)
    {
        double raise = this.salary * byPercent /100;
        this.salary += raise;
    }
}

 

1.1 继承层次

       有一个公共超类派生出的所有类的集合被称为继承层次,在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链。通常一个祖先类可以有多个子孙继承链。

1.2 多态

       在Java中,对像变量是多态的。一个Employee变量既可以引用一个Emlopyee类对象,也可以引用一个Employee类的任何一个子类的对象。以上例为例;

        boss.setBonus(5000);

        Employee[] staff = new Employee[3];

        staff[0] = boss;

 这里staff[0]和boss引用同一个对象,但是编译器将staff[0]视为Employee对象。所以可以这样调用

:boss.setBouns(5000);但是不可以这样:staff[0].setBouns(5000);因为staff[0]声明的类型是Employee,而setBouns()不是Employee的方法。

1.3 阻止继承

       在定义类的时候使用final关键字时就表明这个类不允许被扩展。类中方法也可以声明为final,这样子类就不能覆盖这个方法(final类中的所有方法自动的成为final方法)。

1.4 抽象类

       若自下而上仰视类的继承层次结构,会发现位于上层的类更加具有通用性,甚至更抽象。从某种角度看,祖先类更加通用,人们只将它视为派生其他类的基类。例如:我们对Empolee类层次进行拓展。一位雇员是一个人,一个学生也是一个人,我们将Person和Student类添加到类的层次结构。

       每个人都有一些诸如姓名这样的属性。学生与雇员都有姓名属性,因此可以将getName()方法放置在位于继承层次关系较高的通用类中。例如现在要在上例中增加一个getDescriltion方法,它返回对一个人的简短描述。在Empolee和Student类中这个方法很容易实现,但在Person中应该提供什么内容,除了姓名Person一无所知。我们也可以让Person.getDescription()返回一个空字符串,但是更好的方法是使用abstract关键字,这样就可以不实现这个方法。

     抽象方法充当着占位的作用,它们的具体实现在子类中。扩展抽象类有两种选择:

1.在子类中定义部分抽象方法或抽象方法也不定义,这样必须将子类也标记为抽象类

2.定义全部抽象方法,这样子类就不是抽象的了

package Exemple;
abstract class Person {
    private String name;
    public Person(String n)
    {
        name = n;
    }
    public abstract String getDescription();
    public String getName()
    {
        return name;
    }
}
package Exemple;
class Student extends Person{
    private String major;
    public Student(String n, String m)
    {
        super(n);
        major = m;
    }
    public String getDescription()
    {
        return "a student majoring in " + major;
    }
}
package Exemple;
import java.util.*;
 class Employee extends Person{
    private double salary;
    private Date hireDay;
    public Employee(String n, double s, int year, int month, int day)
    {
        super(n);
        salary = s;
        GregorianCalendar calendar = new GregorianCalendar(year,month - 1,day);
        hireDay = calendar.getTime();
    }
    public double getSalary()
    {
        return salary;
    }
    public Date getHireDay()
    {
        return hireDay;
    }

     @Override
     public String getDescription() {
         return String.format("an employee with a salary of $%.2f ",salary);
     }

     public void raiseSalary(double byPercent)
    {
        double raise = this.salary * byPercent /100;
        this.salary += raise;
    }
}
package Exemple;
import java.util.*;
public class PersonTest {
    public static void main(String[] args) {
        Person[] people = new Person[2];

        people[0] = new Employee("Tom",5000,1988,10,1);
        people[1]  = new Student("Maria","computer science");

        for(Person p: people)
        {
            System.out.println(p.getName() + ", " + p.getDescription());
        }
    }
}

 

2. 反射

       能分析类能力的程序被称为反射,反射机制功能很强大,包括;1.在运行中分析类的能力,2.在运行中查看对象,例如:编写一个toString方法共所有类使用,3.实现数组的操作代码,4.利用Method对象。

2.1 Class类

      程序运行期间,系统会为所有对象维护一个被称为运行时的类型标识。这个信息保存着每个对象所属的类足迹。虚拟机利用运行时信息选择相应的方法执行。

      这里介绍个常用的Class类的方法,getName。这个方法返回类的名字,例如;System.out.println(e.getClass().getName()+" " +e.getName());若e是雇员就会输出:Exemple.Employee marry。其中Exemple是包名。

package Exemple;
import java.util.*;
public class PersonTest {
    public static void main(String[] args) {
        Person[] people = new Person[2];
        people[0] = new Employee("Tom",5000,1988,10,1);
        people[1]  = new Student("Maria","computer science");
        Employee e = new Employee("marry",4000,1988,12,1);//新建e对象
        for(Person p: people)
        {
            System.out.println(p.getName() + ", " + p.getDescription());
        }
        System.out.println(e.getClass().getName() + " " +e.getName());//输出对应类名字
    }
}

 

 

      

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值