Java Object类解析

在学过Java的面向对象后,我们都知道“万物皆对象”,Object是所有类的基类,所有类显式或隐式地继承于Object。

下面是Java对Object类的描述:

package java.lang;

/**
 * Class {@code Object} is the root of the class hierarchy.
 * Every class has {@code Object} as a superclass. All objects,
 * including arrays, implement the methods of this class.
 *
 * @author  unascribed
 * @see     java.lang.Class
 * @since   JDK1.0
 */
public class Object {
    ...
}

Object方法

image-20210216134654167

其中,一个private static方法、两个protected方法、9个public方法,而且还存在很多native方法。

registerNatives()

private static native void registerNatives();
static {
    registerNatives();
}

该方法是私有的静态本地方法,在类加载的时候被执行。

作用:对Object类中使用到的几个native方法进行注册。

getClass()

public final native Class<?> getClass();

该方法是一个本地方法,返回一个Class对象,而且不可以被重写。

作用:获取定义当类实例的Class对象。

常用于反射机制中,可以获取类的相关信息。

hashCode()

public native int hashCode();

该方法是一个本地方法,返回一个int值,但可以被重写。

作用:获取当前实例的散列码。该hashCode用来标识对象。

常用于集合框架中对象元素的比较。集合框架中,比如set,map在添加元素时,都是获取hashCode再根据定义的算法来生成hash值,从而来确定添加元素在集合数据结构中的存储位置。

注意:该hashCode不是对象地址

地址:变量在内存中存储位置

hashCode:根据一定散列算法为对象生成的标识码

通过该方法的注释可以知道,各个JVM厂商必须遵循一定的契约(contract):

  • 多次调用同一个对象的HashCode()必须返回同一个整数
  • 如果两个对象的equals比较返回true,要求它们的hashCode方法也必须返回同一个整数
  • 如果两个对象的equals比较返回false,并不要求它们的hashCode方法下相同的整数

当然,因为该方法可以被重写,所以对象的hashCode可以让我们自己指定,但生成hashCode必须满足以上的要求。

equals(Object obj)

public boolean equals(Object obj) {
    return (this == obj);
}

该方法返回一个boolean值,可以被重写。

作用:用来比较两个对象是否相等。

对象的相等比较涉及两种方式:

  • ==运算符:比较引用地址
  • equals方法:比较对象内容

从源码可以看到:

equals方法是默认比较两个对象的地址是否相等。

默认情况下,无法比较两个对象的内容是否一致。

所以,当我们需要比较不同实例对象的内容是否相等时就需要重写该类的equals方法,所指的内容也就是某些属性值。

重写equals方法需要满足一下条件(x,y,z都是相同类的实例对象,且不为空):

  • 自反性:必须有x.equals(x)返回true
  • 对称性:如果x.equals(y)返回true,则y.equals(x)也要返回true
  • 传递性:如果x.equals(y)返回true,且y.equals(z)返回true,则x.equals(z)也要返回true
  • 一致性:相同的两个对象,相同的调用方式,多次调用equals方法必须返回相同的值
  • 非空性:x.equals(null)永远返回false

例:

@Override
	public boolean equals(Object obj) {
        // 相同类实例、非空
		if(!(obj instanceof Student)) {
			return false;
		}
		Student stuObj = (Student) obj;
		// 比较对象地址
		if (this == stuObj) {
			return true;
		}
		// 比较对象内容
		if (stuObj.name.equals(this.name) && stuObj.sex.equals(this.sex) && stuObj.age.equals(this.age)) {
			return true;
		} else {
			return false;
		}
	}

clone()

protected native Object clone() throws CloneNotSupportedException;

该方法是一个被保护的本地方法,可以被重写。

作用:将当前对象的实例复制一份,生成一个新的对象实例。

注意:只有实现了Cloneable接口的类才能调用clone方法,否则会抛出CloneNotSupportedException。

从方法注释我们可以知道:

  • x.clone() != x返回true
  • x.clone().getClass() == x.getClass()返回true,不必须
  • x.clone().equals(x)返回true,不必须

对象的拷贝类型:

  • 浅拷贝

  • 深拷贝

区别:对象中的引用类型属性的引用是否改变。

其本质是:引用类型的属性对象是否重新开辟空间创建。

实现深拷贝:需要将每一层的引用对象都实现Cloneable对象。

toString()

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

作用:返回一个实例对象的字符串表现形式。

具体形式是该实例的类名加上“@”再加上该实例的hashCode的十六进制。一般为了查看到详细的实例信息,都会重新该方法。

wait()

public final void wait() throws InterruptedException {
    wait(0);
}
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
    if (timeout < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException(
                            "nanosecond timeout value out of range");
    }

    if (nanos > 0) {
        timeout++;
    }

    wait(timeout);
}

该方法用于线程通信。

作用:wait及其重载方法(设置等待时间)是让当前线程进入等待状态(会释放锁资源),直到当前线程被唤醒或者等待超时,再次进入就绪状态。

注意:调用wait方法的当前线程必须持有对象监视器(锁资源),否则会抛出IllegalMonitorStateException

调用wait方法的当前线程会立即释放持有的对象监视器,从而让其他线程有机会获取该对象监视器。

notify()

public final native void notify();
public final native void notifyAll();

该方法用于线程通信。

作用:notify和notifyAll都是为了唤醒相同对象监视器上处于等待状态的线程。

不同:

  • notify:当前线程随机唤醒一个相同对象监视器上的等待线程
  • notifyAll:当前线程唤醒相同对象监视器上的所有等待线程

源码注释描述:

Wakes up a single thread that is waiting on this object's
monitor. If any threads are waiting on this object, one of them
is chosen to be awakened. The choice is arbitrary and occurs at
the discretion of the implementation. A thread waits on an object's
monitor by calling one of the {@code wait} methods.

注意:调用notify方法的当前线程必须持有对象监视器,否则会抛出IllegalMonitorStateException

当前线程调用notify方法,会将因为争夺相同对象监视器的其他线程唤醒。但是其他线程不会立即获取到对象监视器,因为当前线程还未释放对象监视器(没有执行完同步代码块)。

finalize()

protected void finalize() throws Throwable { }

该方法只有空方法体,可以重写,但是不建议重写。

作用:通常用于进行一些资源释放。

特点:

  • 在对象被垃圾回收时被JVM调用。
  • 该方法体中抛出的异常会被JVM catch并忽略。
  • 任何对象的finalize方法最多只会被调用一次,并不能保证一定会被调用。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值