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),因为它们被设计成是要被重写的- 任何一个类,它在重写这些方法的时候,都有责任遵守这些通用约定。如果不能做到这一点,其他依赖于这些规定的类(例如
HashMap
和HashSet
)就无法结合该类一起正常运作
3. 什么时候应该重写 equals()
方法
- 如果类具有自己特有的逻辑相等概念(不同于对象等同的概念),而且父类还没有重写
equals()
以实现期望的行为,这时我们就需要重写equals()
方法 - 这通常属于值类(value class)的情形。值类仅仅是一个表示值的类,例如
Integer
或者Date
- 我们在利用
equals()
方法来比较值对象的引用时,通常希望知道它们在逻辑上是否相等,而不是想了解它们是否指向同一个对象
4. equals()
方法的通用约定是
equals()
方法实现了等价关系(equivalence relation)- 自反性(reflexive):对于任何非
null
的引用值x
,x.equals(x)
必须返回true
- 对称性(symmetric):对于任何非
null
的引用值x
和y
,当且仅当y.equals(x)
返回true
时,x.equals(y)
必须返回true
- 传递性(transitive):对于任何非
null
的引用值x
、y
、和z
,如果x.equals(y)
返回true
,并且y.equals(z)
也返回true
,那么x.equals(z)
也必须返回true
- 一致性(consistent):对于任何非
null
的引用值x
和y
,只要equals()
的比较操作在对象中所用的信息没有被修改,多次调用x.equals(y)
就会一致地返回true
,或者一致地返回false
- 非空性(Non-nullity):对于任何非
null
的引用值x
,x.equals(null)
必须返回false
- 自反性(reflexive):对于任何非
5. 为什么重写 equals()
方法时总要重写 hashCode()
方法
Object
规范 [Java SE6] 的Object.hashCode()
通用约定第二条是:相等的对象必须具有相等的散列码(hash code
)- 如果没有遵守上述约定,就会导致该类无法结合所有基于散列的集合一起正常运作
- 这样的集合包括
HashMap
、HashSet
和Hashtable
6. toString()
方法的内部实现原理
1 | public String toString() { |
7. toString()
方法的内部实现为什么要这么写
- 写类名是可以理解的,表示对象的类型,而写哈希值则是不得已的
- 因为
Object
类并不知道具体对象的属性,不知道怎么用文本描述,但又需要区分不同对象,只能是写一个哈希值
8. 怎么理解 extends
关键字
Java
使用extends
关键字表示继承关系,一个类最多只能有一个父类,即:单根继承- 子类不能直接访问父类的私有属性和方法
- 除了私有的外,子类继承了父类的其他属性和方法
- 还可以用于接口扩展
9. 怎么理解 super
这个关键字
super
这个关键字用于指代父类,可用于调用父类构造方法、访问父类方法和变量- 调用父类构造方法时,
super
必须放在第一行 super
同样可以引用父类非私有的变量
10. super
和 this
的区别
this
引用一个对象,是实实在在存在的,可以作为方法参数,可以作为返回值super
只是一个关键字,不能作为参数和返回值,它只是用于告诉编译器访问父类的相关变量和方法
11. 怎样理解多态、向上转型、动态绑定这几个概念
- 多态:子类对象可以赋值给父类引用变量
- 向上转型:转型就是转换类型,向上转型就是转换为父类类型,本质和多态是一样的
- 动态绑定:多态之后,实际执行调用的是子类实现
12. 为什么要有多态和动态绑定
- 创建对象的代码和操作对象的代码经常不在一起,操作对象的代码往往只知道对象是某种父类型,也往往只需要知道它是某种父类型就可以了
- 多态和动态绑定是计算机程序的一种重要思维方式(面向对象的里氏替换原则),使得操作对象的程序不需要关注对象的实际类型,从而可以统一处理不同对象,但又能实现每个对象的特有行为
- 操作统一行为就调用父类,操作特定行为就调用子类
13. new
过程的执行顺序是怎样的
new
过程中,父类先进行初始化,可通过super
调用父类相应的构造方法- 没有使用
super
的情况下,调用父类的默认构造方法