0%

Java 类的继承(一):基本概念

1. Object 类里的方法有

  • Object没有定义属性,但定义了一些方法(源码基于 JDK 7.0)

  • public 方法

    • public native int hashCode(); // 用于获取对象的哈希值(没有 final 修饰,可以被子类重写)
    • public final native Class<?> getClass(); // 返回此 Object 的运行类
    • public boolean equals(Object obj) { return (this == obj); } // 用于确认两个对象是否“相同”
    • public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode()); } // 返回该对象的字符串表示
    • public final native void notify(); // 唤醒在此对象监视器上等待的单个线程
    • public final native void notifyAll(); // 唤醒在此对象监视器上等待的所有线程
    • public final void wait() throws InterruptedException { wait(0); } // 用于让当前线程失去操作权限,当前线程进入等待序列
    • public final native void wait(long timeout) throws InterruptedException; // 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,让当前线程等待
    • public final void wait(long timeout, int nanos) throws InterruptedException {} // 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量前,让当前线程等待
  • private 方法

    • private static native void registerNatives() // 私有方法
  • protected 方法

    • protected native Object clone() throws CloneNotSupportedException; // 创建并返回此对象的一个副本
    • protected void finalize() throws Throwable // 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法

2. 怎样理解 Object

  • 尽管 Object 是一个具体类,但设计它主要是为了扩展
  • Object 所有的final 方法equals()hashCode()toString()clone()finalize()) 都有明确的通用约定(general contract),因为它们被设计成是要被重写的
  • 任何一个类,它在重写这些方法的时候,都有责任遵守这些通用约定。如果不能做到这一点,其他依赖于这些规定的类(例如 HashMapHashSet)就无法结合该类一起正常运作

3. 什么时候应该重写 equals() 方法

  • 如果类具有自己特有的逻辑相等概念(不同于对象等同的概念),而且父类还没有重写 equals() 以实现期望的行为,这时我们就需要重写 equals() 方法
  • 这通常属于值类(value class)的情形。值类仅仅是一个表示值的类,例如 Integer 或者 Date
  • 我们在利用 equals() 方法来比较值对象的引用时,通常希望知道它们在逻辑上是否相等,而不是想了解它们是否指向同一个对象

4. equals() 方法的通用约定是

  • equals() 方法实现了等价关系(equivalence relation)
    • 自反性(reflexive):对于任何非 null 的引用值 xx.equals(x) 必须返回 true
    • 对称性(symmetric):对于任何非 null 的引用值 xy,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 必须返回 true
    • 传递性(transitive):对于任何非 null 的引用值 xy、和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 也返回 true,那么 x.equals(z) 也必须返回 true
    • 一致性(consistent):对于任何非 null 的引用值 xy,只要 equals() 的比较操作在对象中所用的信息没有被修改,多次调用 x.equals(y) 就会一致地返回 true,或者一致地返回 false
    • 非空性(Non-nullity):对于任何非 null 的引用值 xx.equals(null) 必须返回 false

5. 为什么重写 equals() 方法时总要重写 hashCode() 方法

  • Object 规范 [Java SE6] 的 Object.hashCode() 通用约定第二条是:相等的对象必须具有相等的散列码(hash code
  • 如果没有遵守上述约定,就会导致该类无法结合所有基于散列的集合一起正常运作
  • 这样的集合包括 HashMapHashSetHashtable

6. toString() 方法的内部实现原理

1
2
3
public String toString() {
return getClass.getName() + "@" + Integer.toHexString(hasCode()));
}

7. toString() 方法的内部实现为什么要这么写

  • 写类名是可以理解的,表示对象的类型,而写哈希值则是不得已的
  • 因为 Object 类并不知道具体对象的属性,不知道怎么用文本描述,但又需要区分不同对象,只能是写一个哈希值

8. 怎么理解 extends 关键字

  • Java 使用 extends 关键字表示继承关系,一个类最多只能有一个父类,即:单根继承
  • 子类不能直接访问父类的私有属性和方法
  • 除了私有的外,子类继承了父类的其他属性和方法
  • 还可以用于接口扩展

9. 怎么理解 super 这个关键字

  • super 这个关键字用于指代父类,可用于调用父类构造方法访问父类方法和变量
  • 调用父类构造方法时,super 必须放在第一行
  • super 同样可以引用父类非私有的变量

10. superthis 的区别

  • this 引用一个对象,是实实在在存在的,可以作为方法参数,可以作为返回值
  • super 只是一个关键字不能作为参数和返回值,它只是用于告诉编译器访问父类的相关变量和方法

11. 怎样理解多态、向上转型、动态绑定这几个概念

  • 多态:子类对象可以赋值给父类引用变量
  • 向上转型:转型就是转换类型,向上转型就是转换为父类类型,本质和多态是一样的
  • 动态绑定:多态之后,实际执行调用的是子类实现

12. 为什么要有多态和动态绑定

  • 创建对象的代码和操作对象的代码经常不在一起,操作对象的代码往往只知道对象是某种父类型,也往往只需要知道它是某种父类型就可以了
  • 多态和动态绑定是计算机程序的一种重要思维方式面向对象的里氏替换原则),使得操作对象的程序不需要关注对象的实际类型,从而可以统一处理不同对象,但又能实现每个对象的特有行为
  • 操作统一行为就调用父类,操作特定行为就调用子类

13. new 过程的执行顺序是怎样的

  • new 过程中,父类先进行初始化,可通过 super 调用父类相应的构造方法
  • 没有使用 super 的情况下,调用父类的默认构造方法
-------------------- 本文结束感谢您的阅读 --------------------