《Java核心技术卷1》笔记:第5章 继承

5.1 类、子类、超类

5.1.6 理解方法的调用

弄清楚如何在对象上应用方法调用非常重要 。 下面假设要调用 x.f (args), 隐式参数 x 声明为类 C 的一个对象。 下面是调用过程的详细描述 :

(1 ) 编译器査看对象的声明类型和方法名 。
(2 ) 接下来, 编译器将査看调用方法时提供的参数类型 。 如果在所有名为 f的方法中存在一个与提供的参数类型完全匹配, 就选择这个方法 。 这个过程被称为重栽解析
(3 ) 如果是 private 方法 、 static 方法 、 final 方法 ( 有关 final 修饰符的含义将在下一节讲
述 ) 或者构造器 , 那么编译器将可以准确地知道应该调用哪个方法 , 我们将这种调用方式称为静态绑定

4 ) 当程序运行, 并且采用动态绑定调用方法时 ,虚拟机一定调用与 x 所引用对象的实际类型最合适的那个类的方法。

所谓最合适:
假设 x的实际类型是 D, 它是 C 类的子类 。 如果 D 类定义了方法 f ( String ), 就直接调用它 ; 否则 , 将在 D 类的超类中寻找 f ( String ) , 以此类推 。

每次调用方法都要进行搜索, 时间开销相当大 。 因此 , 虚拟机预先为每个类创建了一个方法表 ( method table ) , 其中列出了所有方法的签名和实际调用的方法。 这样一来 , 在真正调用方法的时候 ,虚拟机仅查找这个表就行了。 在前面的例子中 , 虚拟机搜索D 类的方法表, 以便寻找与调用 f ( Sting ) 相配的方法

例如:e.getSalary ( ) 的详细过程
由于 getSalary 不是 private 方法 、 static 方法或 final 方法 , 所以将采用动态绑定 。
在运行时 , 调用 e . getSalaryO 的解析过程为 :

(1 ) 首先, 虚拟机提取 e 的实际类型的方法表 。 既可能是 Employee 、 Manager 的方法表 ,也可能是 Employee 类的其他子类的方法表。

(2 ) 接下来 , 虚拟机搜索定义 getSalary 签名的类。 此时 , 虚拟机已经知道应该调用哪个方法。

(3 ) 最后, 虚拟机调用方法 。

动态绑定有一个非常重要的特性 :无需对现存的代码进行修改,就可以对程序进行扩展

5.1.7 final 与方法的内联优化

在早期的 Java 中, 有些程序员为了避免动态绑定带来的系统开销而使用 final关键字。

如果一个方法没有被覆盖并且很短 , 编译器就能够对它进行优化处理,这个过程为称为内联(inlining)。

例如 , 内联调用 e.getName () 将被替换为访问 e.name 域 。 这是一项很有意义的改进, 这是由于 CPU 在处理调用方法的指令时 ,使用的分支转移会扰乱预取指令的策略 , 所以, 这被视为不受欢迎的 。

然而 , 如果 getName 在另外一个类中被覆盖 , 那么编译器就无法知道覆盖的代码将会做什么操作, 因此也就不能对它进行内联处理了 。

幸运的是, 虚拟机中的即时编译器比传统编译器的处理能力强得多 。 这种编译器可以准确地知道类之间的继承关系 , 并能够检测出类中是否真正地存在覆盖给定的方法。 如果方法很简短 、 被频繁调用且没有真正地被覆盖 , 那么即时编译器就会将这个方法进行内联处理。

如果虚拟机加载了另外一个子类, 而在这个子类中包含了对内联方法的覆盖 , 那么将会发生什么情况呢 ? 优化器将取消对覆盖方法的内联。 这个过程很慢 ,但却很少发生。

5.1.8 强制类型转换

将一个值存人变量时 , 编译器将检查是否允许该操作。 将一个子类的引用赋给一个超类变量 , 编译器是允许的。 但将一个超类的引用赋给一个子类变量 ,必须进行类型转换 , 这样才能够通过运行时的检査。

当类型转换失败时 , Java 不会生成一个 null 对象 ,而是抛出一个异常。
所以在 Java 中 , 需要将 instanceof 运算符和类型转换组合起来使用 :

if(staff[1] instanceof Manager)
{
   
Manager boss = (Manager) staff[1];
}

5.1.10 protected

子类也不能访问超类的私有域。
然而, 在有些时候 , 人们希望超类中的某些方法允许被子类访问 ,或允许子类的方法访问超类的某个域。 为此 , 需要将这些方法或域声明为 protected 。

事实上, Java 中的受保护部分对所有子类及同一个包中的所有其他类都可见。
下面归纳一下 Java 用于控制可见性的 4 个访问修饰符 :
1 ) 仅对本类可见 private。
2 ) 对所有类可见 public :
3 ) 对本包和所有子类可见 protected。
4 ) 对本包可见 — 默认 ( 很遗憾 ) ,不需要修饰符。

5.2 Object类

5.2.1 equals方法

public class Employee
public boolean equals ( Object otherObject )
{
   

	if ( this = = otherObject ) return true ;

	if ( otherObject = = null ) return false ;

	//判断所属的类型是否相同
	if ( getClassO ! = otherObject . getClass ( )</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_popo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值