JAVA学习---Object类
Posted 易小顺
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA学习---Object类相关的知识,希望对你有一定的参考价值。
文章目录
Object类
1、 简介
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进行数据的转换时,直接使用就行。
2、 作用
由于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(); // 王小二
3、 方法解释
3.1、 方法摘要
变量和类型 | 方法 | 描述 |
---|---|---|
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) | 对于超时时间有着更细粒度的控制 |
3.2、 方法详情
3.2.1 、toString()
返回一个字符串,类 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 + '\\'' +
'}';
}
3.2.2 、equals(Object obj)
指示某个对象是否 等于
此对象,类 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
- 覆写方法,实现自定义类的比较(同时覆盖 hashCode 方法,以便维护 hashCode 方法的常规协定,声明相等的对象必须具有相等的
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 |
3.2.3 、hashCode()
返回对象的哈希码值,也就是通过对关键字的 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) 方法不一定相同 |
3.2.4 、getClass()
返回此 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
3.2.5 、clone()
创建并返回此对象的副本,和原对象不指向同一块地址。
首先,如果此对象的类未实现接口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是任何引用或基本类型。 否则,此方法创建此对象的类的新实例,并使用该对象的相应字段的内容初始化其所有字段,就像通过赋值一样; 这些字段的内容本身不会被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深拷贝”操作。
3.2.6 、wait()
导致当前线程进入 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;
代码测试
学完多线程之后再做补充
3.2.7 、notify()
用于唤醒一个在此对象监视器上等待的线程, 如果所有的线程都在此对象上等待,那么只会选择一个线程,选择是任意性的,并在对实现做出决定时发生。
一次只有一个线程可以拥有对象的监视器。
此方法只应由作为此对象监视器所有者的线程调用。 线程以三种方式之一成为对象监视器的所有者
-
-
通过执行该对象的同步实例方法。
-
通过执行在对象上同步的
synchronized
语句的主体。 -
对于类型为
Class
的对象,通过执行该类的同步静态方法。
-
-
内部源码
@HotSpotIntrinsicCandidate
public final native void notify();
代码测试
学完多线程之后再做补充
3.2.8 、notifyAll()
和 notify
功能类似,唤醒等待此对象监视器上的所有线程。
内部源码
@HotSpotIntrinsicCandidate
public final native void notifyAll();
- 方法测试
学完多线程之后再做补充
tIntrinsicCandidate
public final native void notify();
代码测试
学完多线程之后再做补充
以上是关于JAVA学习---Object类的主要内容,如果未能解决你的问题,请参考以下文章