5.1.1 定义子类
派生于 == 继承于。
已经存在的类称为父类(parent class)、基类(base class)、超类(superclass);
新类称为子类(subclass)、派生类(derived class)或孩子类(child class)。
在通过扩展超类定义子类的时候,仅需要指出子类与超类的不同之处。因此在设计子类的时候,应该将通用的方法放在超类中,而将具有特殊用途的方法放在子类中。
5.1.2覆盖方法
调用父类方法:
super.getXXX();
有些人认为super与this引用是类似的概念,实际上,这样比较并不太恰当。这是因为super不是一个对象的引用,不能将super赋给另外一个对象变量,它只是一个指示编译器调用超类方法的特殊关键字。
5.1.3子类构造器
如果子类的构造器没有显式的调用超类的构造器,则将自动地调用超类默认(无参)的构造器。如果超类没有不带参数的构造器,并且在子类的构造器中又没有显式地调用超类的其它构造,则Java编译器将报告错误。
this关键字的用途
引用隐式参数;
调用该类其它的构造器;
super关键字的用途
调用超类的方法;
调用超类的构造器;
Manager boss = new Manager("Tom",8000,20);
boss.setBonus(5000);
//Manager是子类 Employee是子类
Employee [] staff = new Employee[3];
staff[0] = boss;
staff[1] = new Employee("Jack",4000,21);
staff[2] = new Employee("JackLove",6000,22);
for(Employee e : staff){
System.out.println(e.getSalary());
}
当e引用Employee对象时,e.getSalary()调用的是Employee中的getSalary方法;当e引用Manager对象时,e.getSalary()调用的是Manager中的getSalary方法,虚拟机知道e实际引用的对象类型。
一个对象变量(例如,变量e可以指示多种实际类型的现象被称为多态。) 在运行时能够自动地选择调用哪个方法的现象称为 动态绑定。
如果不希望一个方法具有虚拟特征,可以将它标记为final。
5.1.4继承层次
由一个公共超类派生出来的所有类的集合被称为 继承层次。 在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链。
5.1.5 多态
"is-a"规则,它表明每个子类的对象也是超类的对象。
“置换法则”,它表明程序中出现超类对象的任何地方都可以用子类置换。
在Java中,对象变量是多态的。
不能将一个超类的引用赋给子类变量。
5.1.6理解方法调用
编译器查看对象的声明类型和方法名。
编译器查看调用方法时提供的参数类型。
如果是private static final方法或者构造器,那么编译器将可以准确的知道应该调用哪个方法,称为"静态绑定"。
程序运行时,采用动态绑定调用方法时,虚拟机一定调用与x所引用对象的实际类型最合适的那个类方法。
如果超类是public,子类也一定是public。
5.1.7阻止继承:final类和方法
如果一个方法们没有被覆盖并且很短,编译器就会对它进行优化处理,这个过程称为内联(inlining)。
5.1.8 强制转换类型
子类引用可以赋值给超类变量,但是,超类引用赋给子类变量时,必须类型转换。
在进行类型转换之前,先查看一下是否能够成功地转换。例如if(staff[1] instanceof Manager){ boss = (Manager)staff[1]; }
综上所诉
只能在继承层次内进行类型转换。
将超类转换为子类之前,应该使用instanceof进行检查。
不推荐类型转换,一般情况下,应该尽量少用类型转换和instanceof运算符。
5.1.9抽象类
类即使不含抽象方法,也可以声明为抽象类。
抽象类不能被实例化。如果将一个类声明为abstract,就不能直接创建这个类的对象。例如,表达式: new AbstractObject();但是可以创建一个具体的子类对象;
AbstractObject ab = new SubObject(); //这里的ab 是一个抽象类AbstractObject 的变量,AbstractObject 引用了一个非抽象子类SubObject的实现;
由于不能构造抽象类AbstractObject的对象,所以变量ab永远不会引用 AbstractObject,而是引用具体的子类对象。
5.1.10受保护访问
private 仅对本类;
protected 本包和子类;示例:Object中的clone()方法。
对本包可见-默认(不需要修饰符);