目录
阻止继承:final类和方法
强制类型转换
抽象类
受保护访问
理解方法调用
-
假设要调用x.(args),隐式参数为类C的一个对象。下面时调用过程的详细描述
-
编译器查看对象的声明类型和方法名
-
接下来编译器要确定方法调用中提供的参数类型。因为可能存在多个方法方法名一样,但是参数不一样,编译器需要根据参数时字符串型还是其他类型,来选择正确的方法来调用
-
如果是private方法,static方法,final方法或者构造器,那么编译器将准确的直到要调用哪个方法。这叫做静态绑定,与此对应的时,如果要调用的方法依赖于隐式参数的实际类型,那么必须在运行时使用动态绑定。
-
程序运行并采用动态绑定时,虚拟机必须调用x索引用的那个类的实际类型对应的那个方法。假设x的实际类型时D,它是C类的子类,如果在D类定义了这个方法那么就会调用D类的这个方法,否则就在D类的父类C类中寻找此方法,以此类推。
-
每次调用方法都会完成这个搜索,时间开销很大,因此虚拟机为每个类计算了一个方法表,其中列出来所有的方法的签名(方法的签名:方法的名字和参数列表)和要实际调用的方法,虚拟机仅需要查找这个表就行了
-
-
-
动态绑定的重要特性:
无需对现有的代码进行修改就能对程序进行扩展。假设有一个新类Executive,并且变量e有可能引用这个类的对象,我们不需要对e.getSalary()的代码重新编译,如果e恰好引用了一个Excutive类的对象,就会自动的调用Excutive类的getSalary方法
-
注意:在重写一个方法时,子类的方法可见性不能低于超类的,特别的如果超类的方法的可见性时public那么子类的方法也必须声明为public
-
有时候我们希望阻止人们利用某些类来定义子类,不允许扩展的类称为final类,如果在定义类的时候使用了final修饰符,就代表这个类是final类
-
例如如果不想让人们派生Excutive类就在定义Excutive类的时候定义下面的语句
public final class Excutive extends Manager{ ... }
-
类中的某个方法也可以声明为final这样子类就不能重写这个方法了
-
注意final类的方法自动变为final方法
-
-
将方法声明为final的主要原因:确保不会在子类中改变语义。例如:Calender类中的getName和setName都设置为final,这表明了只允许Calender类的设计者负责Date类与日历状态的转化,而不允许子类来添乱。同样的String类也是final类型,意味着不允许任何人定义String的子类。换一句话说就是,如果有一个String引用,它引用的一定是一个String对象,而不可能是其他类的对象。
-
正像有时候需要将浮点数转换为整数一样,有时候也需要将一个类的对象引用转换为另一个类的对象引用
-
语法:需要将目标类名用圆括号括起来,并放在需要转换的对象引用之前就可以了
Manager boss=(Manager)staff[0];
-
注意:将一个子类引用赋值给超类变量这样是允许的,但将一个超类引用赋值给一个子类变量,这样不可以staff是Employee类型的
Manager boss=(Manager)staff[0]//Error
因为不是所有的员工都是经理
-
所以在此之前应该使用instanceof *** 作符来查看能否成功的转换
if(staff[0] instanceof Manager){ boss=(Manager)staff[1]; ... }
-
强制类型转换注意点:
-
只能在继承层次内进行强制类型转换
-
在将超类转换为子类之前,应当使用instanceof进行检查
-
-
abstract修饰符可以用来修饰类或者方法,修饰方法就是抽象方法,修饰类就是抽象类
-
抽象类中可以没有抽象方法,但是有抽象方法的类一定是抽象类
-
对于抽象类:
-
不能使用new关键字来创建对象,它是用来让子类继承的
-
-
对于抽象方法:
-
只有方法的声明没有方法的实现,它是用来让子类实现的。例如Person类下有两个子类分别是,Student类,和Employee类,在两个子类中都有一个歌坛getDescription()方法,这个方法返回对一个人的简短描述,但在Person类中处理这个人的姓名别的什么都不能提供,这时就让Person.getDescription返回空,但更好地办法时让其声明为abstract
-
-
除了抽象方法外,抽象类还可以包含具体的字段和方法,像Person类还有一个name的字段,和一个getName()的方法
-
可以定义一个抽象类的变量,但是这样的一个变量只能引用非抽象子类的对象
Person a=new Studnet();
-
子类继承抽象类,那么就必须实现抽象类没有实现的抽象方法,否则该子类也应该定义为抽象类
-
抽象类中也有构造函数,而且抽象类的构造函数是起作用的,而且在实例化子类对象时首先构调用的是抽象类的构造函数,再调用子类的构造函数
-
有些时候,可能希望超类中的某个方法只允许子类进行访问,或者更少见的,只允许子类中的某个方法访问超类的某个字段,为此,需要将这些类或者字段声明为受保护的(protected)
-
在Java中只允许同一个包中的类访问保护字段现在有一个Employee的子类,这个子类在不同的包中,这个子类的方法只能查看自己对象的hireDay字段,而不能查看其他Employee对象的字段,有了这个机制就能避免滥用保护机制,不能通过派生子类来访问受保护字段
-
受保护的方法更具有保护意义,将方法声明为protected这样就可以让子类正确的访问,而其他类不行
-
Java的三个访问控制修饰符:
-
仅对本类可见private
-
对外部完全可见public
-
对本包和所有子类可见protected
-
参考书籍:Java核心技术 卷1(原书第11版)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)