Object类是Javajava.lang
包下的核心类,是类层次结构的根,Object类是所有类的父类,任何一个类都间接或直接继承至Object类,所有对象(包括数组)都实现此类的方法。
如果一个类没有直接明确继承哪一个类,那么它就是Object的直接子类。
// 隐式继承
class People {
//
}
// 显示继承
class Student extends Object {
//
}
System.out.println(new People() instanceof Object); // true
System.out.println(new Student() instanceof Object); // true
Object 类属于java.lang
包,此包下的所有类在使用时无需手动导入,系统会在程序编译期间自动导入,因此在使用Object进行数据的转换时,直接使用就行。
由于Object作为所有类的父类,因此可以接受所有的 引用数据类型,通过向下转型进行使用。
class People {
// 姓名
private String name;
public People() {
this.name = "王小二";
}
public void print() {
System.out.println(this.name);
}
}
Object object = new People();
((People) object).print(); // 王小二
变量和类型 | 方法 | 描述 |
---|---|---|
Object() |
构造方法,构造一个新对象 | |
protected Object |
clone() |
创建并返回此对象的副本 |
boolean |
equals(Object obj) |
指示某个其他对象是否“等于”此对象 |
protected void |
finalize() |
|
Class> |
getClass() |
返回此 Object 的运行时类 |
int |
hashCode() |
返回对象的 哈希码值 |
void |
notify() |
唤醒正在此对象监视器上等待的一个线程 |
void |
notifyAll() |
唤醒等待此对象监视器的所有线程 |
String |
toString() |
返回对象的 字符串 表示形式 |
void |
wait() |
导致当前线程进入 WAITING 状态,等待其他线程 唤醒 或是被 中断,会释放对象锁 |
void |
wait(long timeoutMillis) |
和 wait() 方法一致,只是在等待timeoutMillis 时间后没有通知就会自动超时返回 |
void |
wait(long timeoutMillis, int nanos) |
对于超时时间有着更细粒度的控制 |
返回一个字符串,类 Object 对象的 toString 返回值由该对象为实例的类的名称、符号字符 @
以及对象的哈希码的无符号十六进制表示形式组成,也就是返回一个表示该对象的 值
的字符串。
内部源码
public String toString() {
return this.getClass().getName() + "@" + Integer.toHexString(this.hashCode());
}
代码测试
Object object = new Object();
object.toString(); // java.lang.Object@129a8472
// 以People类为例
@Override
// 覆写toString方法,返回当前对象的信息
public String toString() {
return "People{" +
"name='" + name + '\'' +
'}';
}
指示某个对象是否 等于
此对象,类 Object 对象的 equals 实现最具有区别的等价关系,也就是说任何非空的对象 x
和 y
,当且仅当 x
和 y
指向同一块地址内存时,才返回 true (也就是内部实现 == 操作)。
内部源码
public boolean equals(Object obj) {
return this == obj;
}
代码测试
Object obj1 = new People();
Object obj2 = new People();
Object obj3 = obj1;
obj1.equals(obj2); // false
obj1.equals(obj3); // true
obj1 == obj2; // false
obj1 == obj3; // true
hash
值)。 @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
People people = (People) o;
return name.equals(people.name);
}
equals
方法在非null对象引用上实现等价关系。关系 | 解释 |
---|---|
对称性 | 对于任何非空的对象x ,x.equals(x) 应该返回true |
自反性 | 对于任何非空对象x 和y ,x.equals(y) 应该返回true 当且仅当y.equals(x) 返回true |
传递性 | 对于任何非空对象x ,y 和z ,如果x.equals(y) 返回true 个y.equals(z) 返回true ,然后x.equals(z) 应该返回true |
一致性 | 对于任何非空对象x 和y ,多次调用x.equals(y) 始终返回true 或始终返回false ,前提是未修改对象上的equals 比较中使用的信息 |
非空性 | 对于任何非空的参考值x , x.equals(null) 应该返回false |
返回对象的哈希码值,也就是通过对关键字的 hash
运算,计算在 hash表 中的的存储位置,并非对象的 物理地址。
内部源码
是本地方法。 @HotSpotIntrinsicCandidate
public native int hashCode();
代码测试
Object obj = new People();
obj.hashCode(); // 未进行覆写 453211571
覆写
将 equals 所比较的属性作为关键字,保证相同的对象具有一样的哈希码值。 @Override
public int hashCode() {
return Objects.hash(name);
}
Object obj = new People();
obj.hashCode(); // 进行覆写 29176135
hashCode
的规则。结论 |
---|
只要在执行Java应用程序期间多次在同一对象上调用它, hashCode 方法必须始终返回相同的整数,前提是不修改对象上的 equals 比较中使用的信息。 从应用程序的一次执行到同一应用程序的另一次执行,该整数不需要保持一致。 |
如果两个对象根据 equals(Object) 方法相等,则对两个对象中的每个对象调用hashCode 方法必须生成相同的整数结果。 |
如果两个对象根据不相等 equals(Object) 方法,然后调用 hashCode 在各两个对象的方法必须产生不同的整数结果,不等对象生成不同的整数结果可能会提高哈希表的性能。 |
hashCode 返回的整数值相同,其equals(Object) 方法不一定相同 |
返回此 Object 的运行时类,返回的类对象是由所表示的类的 static synchronized 方法锁定的对象(也就是返回当前对象所指向的类的类名,引用改变时,相应的返回值也会改变)。
内部源码
@HotSpotIntrinsicCandidate
public final native Class<?> getClass();
代码测试
Object obj = new Object();
obj.getClass(); // class java.lang.Object
obj = new People();
obj.getClass(); // class People
创建并返回此对象的副本,和原对象不指向同一块地址。
首先,如果此对象的类未实现接口Cloneable
,则抛出CloneNotSupportedException
异常,因此在实现此功能时需要继承 Cloneable 接口,这是一个标记接口,不需要实现方法。
内部源码
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
方法实现
我们不能直接覆写 clone 方法,因为他是受保护权限修饰的,因此我们需要定义一个public
权限修饰的 clone 方法,来调用父类的该方法进行数据获取。 public Object clone() {
People copy = null;
try {
copy = (People) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copy;
}
代码测试
People people = new People();
people.clone() == people; // false
people.clone().getClass() == people.getClass(); // true
people.clone().equals(people); // true
Cloneable
并且数组类型 T[]
的 clone
方法的返回类型是 T[]
,其中T是任何引用或基本类型。 否则,此方法创建此对象的类的新实例,并使用该对象的相应字段的内容初始化其所有字段,就像通过赋值一样; 这些字段的内容本身不会被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深拷贝”操作。导致当前线程进入 WAITING 状态,等待其他线程 唤醒 或是被 中断。在执行两个方法时,要先获得锁,当线程执行wait()时,会把当前的锁释放,然后让出CPU。
wait()
内部调用wait(long timeoutMillis)
方法,只是时间设置为0
wait(long timeoutMillis, int nanos)
对时间有着更加精确的设置,第一个 long 时间精确为毫秒,第二个 int 时间精确为纳秒。
内部源码
public final void wait() throws InterruptedException {
this.wait(0L);
}
public final native void wait(long var1) throws InterruptedException;
代码测试
学完多线程之后再做补充
用于唤醒一个在此对象监视器上等待的线程, 如果所有的线程都在此对象上等待,那么只会选择一个线程,选择是任意性的,并在对实现做出决定时发生。
一次只有一个线程可以拥有对象的监视器。
此方法只应由作为此对象监视器所有者的线程调用。 线程以三种方式之一成为对象监视器的所有者
通过执行该对象的同步实例方法。
通过执行在对象上同步的 synchronized
语句的主体。
对于类型为 Class
的对象,通过执行该类的同步静态方法。
内部源码
@HotSpotIntrinsicCandidate
public final native void notify();
代码测试
学完多线程之后再做补充
和 notify
功能类似,唤醒等待此对象监视器上的所有线程。
内部源码
@HotSpotIntrinsicCandidate
public final native void notifyAll();
学完多线程之后再做补充
tIntrinsicCandidate
public final native void notify();
代码测试
学完多线程之后再做补充