Java核心技术学习笔记_2(继承与反射)

Create by westfallon on 8/9

继承

  • 利用继承,人们可以基于已存在的类构造一个新类。继承已存在的类就是复用这些类的方法和域,在此基础上还可以添加一些新的方法和域,以满足新的需求

类、超类和子类

  • Java 中 extends 关键字表示继承
  • Java 与 C++ 定义继承类的方式十分类似。Java 用关键字 extends 代替了 C++ 中的冒号( : )。在 Java 中,所有的继承都是公有继承,而没有C++中私有继承和保护继承
  • extends 表明正在构造的新类派生于一个已经存在的类。已存在的类称为超类(superclass)、基类(base class)或父类(parent class);新类称为子类(subclass)、派生类(derived class)或孩子类(child class)

super关键字

  • 调用超类的方法
  • 调用超类的构造器

继承层次

  • 由一个公共超类派生出来的所有类的集合被称为继承层次(inheritance hierarchy)
  • 在继承层次中,从某个特定的类到其祖先的路径被称为该类的继承链

多态

  • 一个对象变量可以指示多种实际类型的现象叫做多态(polymorphism)
  • 在Java中,子类数组的引用可以转换成超类数组的引用,而不需要采取强制类型转换

动态绑定

  • 在运行时能够自动地选择调用哪个方法的现象叫做动态绑定(dynamic binding)
  • 调用对象方法的执行过程:
    • 编译器查看对象的声明类型和方法名
    • 编译器将查看调用方法时提供的参数类型,如果函数名与参数类型完全匹配,就选择这个方法。这个过程叫做重载解析
    • 如果是private方法、static方法、final方法或者构造器,编译器可以准确地知道应该调用哪个方法,这种调用方式叫做静态绑定(static binding)。与此对应的是,调用的方法依赖于隐式参数的实际类型,并且在运行时实现动态绑定
    • 当程序运行,并且采用动态绑定调用方法时,虚拟机一定调用与所引用对象的实际类型最合适的那个类的方法
  • 动态绑定有一个非常重要的特性:无需对象有的代码进行修改,就可以对程序进行扩展
  • 在覆盖一个方法的时候,子类方法不能低于超类方法的可见行。特别是,如果超类方法是public,子类方法一定要声明public

final类和方法

  • 不允许扩展的类称为final类
  • 类中的特定方法也可以被声明为final。如果这样做,子类就不能覆盖这个方法,final类中所有方法自动称为final方法
  • 对于final域来说,构造对象之后就不允许再改变它们的值了。不过,如果将一个类声明为final,只有其中的方法自动地成为final,而不包括域
  • 将方法或类声明为final的主要目的是:确保它们不会再子类中改变语义

类型转换

  • 将一个子类的引用赋给一个超类变量,编译器是允许的。但将一个超类引用赋给一个子类变量,必需进行类型转换
  • 在进行类型转换之前,应该先查看一下能否成功转换,可以使用 instanceof 运算符实现

抽象类

  • 包含一个或多个抽象方法的类本身必须被声明为抽象的
  • 抽象方法充当着占位的角色,它们的具体实现在子类中
  • 抽象类不能被实例化

Object 类

  • 如果没有明确的指出超类,Object类就被视为是这个类的超类

equals方法

  • Object类中的equals方法用于检测一个对象是否等于另外一个对象
  • equals特性:
    • 自反性:对于任何非空引用x,x.equals(x)应当返回true
    • 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应当返回true
    • 传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true
    • 一致性:如果x和y引用的对象没有发生变化,反复调用x.equals(y)应当返回同样的结果
    • 对于任意非空引用x,x.equals(null)应该返回false
  • 编写equals方法的建议
    • 显式参数命名为otherObject
    • 检测this与otherObject是否引用同一对象
    • 检测otherObject是否为null
    • 比较this与otherObject是否属于同一个类,可以使用getClass检测
    • 将otherObject转换为相应的类型变量
    • 对所有域进行比较

hashCode方法

  • JVM每new一个Object,它都会将这个Object丢到一个Hash哈希表中去,这样的话,下次做 Object的比较或者取这个对象的时候,它会依据对象的hashcode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。详细过程是这样:
    • new Object(),JVM依据这个对象的Hashcode值,放入到相应的Hash表相应的Key上,假设不同的对象确产生了同样的hash值,也就是发 生了Hash key同样导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将全部产生同样hashcode的对象放到这个单链表上去,串在一起。

    • 比较两个对象的时候,首先依据他们的 hashcode去hash表中找他的对象,当两个对象的hashcode同样,那么就是说他们这两个对象放在Hash表中的同一个key上,那么他们一 定在这个key上的链表上。

    • 那么此时就仅仅能依据Object的equal方法来比较这个对象是否equal。当两个对象的hashcode不同的话,肯定他们不能equal.

  • 两个相等对象的equals方法一定为true, 但两个hashcode相等的对象不一定是相等的对象。

反射

  • 反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操控Java代码的程序
  • 能够分析类能力的程序称为反射(reflection),可以用来:
    • 在运行中分析类的能力
    • 在运行中查看对象
    • 实现通用的数组操作代码
    • 利用Method对象

Class类

  • 程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时类型信息选择相应的方法执行
  • 可以通过专门的Java类访问这些信息,保存这些信息的类称为Class
  • 最常用的Class方法是getName,返回类的名字
  • 可以调用静态方法forName获得类名对应的Class对象

继承设计的技巧

  • 将公共操作的域放在超类
  • 不要使用受保护的域
  • 使用继承实现“is-a”关系
  • 除非所有继承的方法都有意义,否则不要使用继承
  • 在覆盖方法时,不要改变预期的行为
  • 使用多态,而非类型信息
  • 不要过多地使用反射
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容