自己做的小总结 摘抄自书本《Java核心技术卷I》
基础知识:
Java的最普通的继承知识,extends关键字将创造一个新的类
又或者叫做子类,extends 后面的跟的类就是所谓的父类或者叫做超类。
子类将继承超类中的特定权限的方法和域
超类中的某个方法并不再适用于子类,这时候子类就可以用相同签名(相同的名字和参数列表)重新定义这个方法。这叫做覆盖,以后子类的对象调用该方法的时候会调用这个新的定义。但是允许覆盖方法的返回类型定义为原返回类型的子类型。
关键字:
多态、动态绑定
一个对象变量可以引用不同类型的对象–多态
在运行时能够自动确定调用哪个方法的现象–动态绑定
private\satic\final 方法在运行前就知道要调用哪个方法–静态绑定
抽象方法、抽象类
protected:对本包和所有子类可见
Object类、clone方法
要注意的:
1.子类无法访问超类的私有成员(private)。私有的定义就是限定了只有当前类有访问权限。
2.超类中定义了
public class Employee{
private String name;
private double salary;
private ...
....(方法)
public double getsalary(){
return salary;
}
}
//子类定义了
public class Manager extends Employee{
...
private double bonus;
public double getsalary(){ //覆盖
return salary + bonus;
}
...
}
好像是这样就能够让Manager类的对象正确get到salary了
但是其实,这里出现了一个继承的权限(我自己设想出来的)问题,就像第一点中所说的,子类无法访问超类的私有成员。
所以这个子类中的覆盖过的方法是子类的方法,没办法访问从父类中集成来的具有父类权限的私有域。
其实继承的本质是:
《Java编程思想》,第129页说”继承不只是复制基类的接口,当创建了一个导出对象时,该对象包含了一个基类的子对象“
隐式地在子类的对象中包含了一个父类的对象,其中包含了父类的私有成员,其实不属于子类的成员,只是包含关系罢了。
如果这里还是想要调用超类的私有成员,那么就使用super关键字。(这里注意一下,考虑到面向对象的封装性质,一般并不直接访问私有域,而是通过访问方法来获得域–>super.getsalary() ; 这就是体现了数据封装的一个点所在。)
3.Employee[] staff = new Employee[3];
Manager boss = new Manager(…);
staff[0] = boss;
这里注意 书上原话是
编译器将staff[0]看做是employee对象,
boss.setBonus(5000); //OK to do this
staff[0].setBonus(5000); // Error
测试的时候发现确实会报错
4.Java中也有c++中类似的虚函数表。
虚拟机为每个类创建了一个方法表,其中列出了所有方法的签名和实际调用的方法。在真正调用方法的,虚拟机只要查找这个表就好了。
> Employee:
> getName() -> Employee.getName()
> getSalary() -> Employee.getSalary()
> getHireDay()->Employee.getHireDay()
> raiseSalary(double)->Employee.raisesSalary(double)
Manager方法略有不同,其中三个方法是继承来的,还有一个重新定义的,还有一个方法是新增加的。
> Manager:
> getName() -> Employee.getName()
> getSalary() -> Manager.getSalary()
> getHireDay()->Employee.getHireDay()
> raiseSalary(double)->Employee.raisesSalary(double)
> setBonus(double)->Manager.setBonus(double)
意思大概是,想调用继承过来的方法,还是得通过Employee类的权限,也就是 Employee.方法(param)…这样
这是一个隐式的过程。
5.关于对象引用变量
每个对象变量都属于一个类型。类型描述了这个变量所引用的以及能够引用的对象类型。
6.关于类的强制类型转换
结合第三点要注意的点来看
参考资料
什么是强制类型转换呢?简单地说,就是把父类型转换为子类型。因为子类型比父类型的内涵要丰富,无非就是属性更多功能更强,所以要把父类型转换为子类型,需要强制,所以叫强制类型转换。那么,是不是只要是父类型的变量就可以转换为子类型呢?事实上不是,这里是有条件限制的
我们用一个类型的构造方法构造出一个对象的时候,对象的类型已经确定了,就是这个类型,但是java允许我们可以不用这个类型的变量引用它,而使用它的父类类型,这时候情况就是我们用一个功能较弱的类型引用了一个功能较强的对象。然而有时候我们又希望这个对象完全发挥它的作用,就需要用一个它本身的类型的变量来引用它,因为原来那个父类的变量是不具备这些功能的,不能使用variablename.function()来使其发挥作用,所以还是用它自己的吧
意思像第三点所说的,不能用staff[0](staff是父类变量数组)来调用子类定义的新方法setBonus(double)
举个例子来说,比如原来定义了两个类型,FatherClass和SonClass,然后构造了一个SonClass类型的对象,用一个FatherClass类型的变量father引用了,就像这样:
FatherClass father = new SonClass();
那么,需要将这个对象的类型还原的时候,就可以用这个表达式。
SonClass son = (SonClass)father;
/*提升能力以后交
给了son变量,因为变量之间的赋值需要相同类型 所以吧
father变量强制类型转换了一下。这里没有改变father变量的
类型
*/其实,father仍然是FatherClass类型,只不过临时把它的能力提升了一下,然后这一切都交给了son这个变量。但是经过这样处理以后,这个对象就真正提升了能力了,在son这个变量的引用之下,从此以后恢复真身,可以自由发挥了。
检查一下是否能够强制类型转换
if(staff[1] instanceof Manager){
boss = (Manager) staff[1] ;
...
}
FatherClass f = new FatherClass();
SonClass s = (SonClass)f;
这是不行的,因为父类变量引用的就是父类的对象,强制类型转换的赋值什么的没错,所以编译能够通过,但是运行的时候会出错。
问题
1.能在子类中用super关键字调用超类中的private方法吗?
不行
public void PublicForPrivate() {
super.PrivateMethod();
System.out.println("This is son class method to use private method from the super class");
}
这是在子类中定义的方法,PrivateMethod()是超类中的private方法,通过super在外部无法调用。
2.为什么能够间接调用父类私有方法?
其实很好理解
当子类继承父类时,子类会继承父类所有的方法(不管这个方法的访问权限是private、protected、public的);只不过在子类自己定义的方法中无法直接去访问继承而来的private方法罢了,但是可以通过继承而来的public及protected方法来间接访问继承而来的private方法。
所以当this.hello();时也就类似了this->father->hello。
即可以简单的将子类的方法分为两个版本,一是继承自父类的方法(简称继承版),二是自己定义的方法(简称自定版义版);但是不管是继承版的还是自定义版的方法,它们都是属于这个子类的(在子类之中,要访问还是通过子类对象的this指针开始一步步的访问,因为coder是不知道有这么个隐式的过程的),所以当子类实例化一个对象去调用这些方法时,这些方法中的this变量肯定指向这个对象本身(只不过访问继承版的private方法时,需要绕一点弯路)
所以输出this指针的时候发现是指向子类对象的地址
且 (this instanceof Son) 表达式也为true。
3.为什么子类能够调用父类私有方法?
子类是不能覆盖(重写)父类的私有方法的。
4.子类和父类的私有方法问题
5.关于反射…(预留)
Java继承与多态详解

被折叠的 条评论
为什么被折叠?



