java.lang.Object--java基础篇

一、简介

Object类是Java中其他所有类基类。Object类没有定义属性,一共有12个方法。

image.png

二、主要方法

1、类构造器 public Object();

Java中规定:在类定义过程中,对于未定义构造函数的类,默认会有一个无参数的构造函数。
所以Object基类自然也有一个无参构造函数。

注意

所有类都有构造函数,未定义构造函数的类,默认一个无参构造函数。但并不是所有类的构造函数都是public的。
复制代码

2、private static native void registerNatives();

registerNatives函数前面有native关键字修饰,native修饰的方法是本地方法,不是java方法,通常都是C/C++实现的,java调用。而本方法就是。这个方法的主要作用就是把C/C++实现的方法映射到java的nativa方法。 这个方法的执行时紧跟着的那段静态代码块实现的

static {
    registerNatives();
}
复制代码

3、public final native Class<?> getClass();

getClass()也是一个native方法,返回的是此Object对象的类对象/运行时类对象Class<?>。效果与Object.class相同。

类:对具有相同特征和行为的实例的抽象

对象:类的一个具体实例

Class:对类的抽象,比如类都具有包名,属性,父类,方法等。

image.png

public native int hashCode();、

约定: 1、java应用程序一次运行过程中,一个对象的hashcode值是相同的,但是多次运行的hashcode值不需要保持一致。
2、equals()相等==>hashcode一定相等
3、hashcode相等 不一定两个对象相等。

public boolean equals(Object obj);

先来看一下Object类中方法的实现

public boolean equals(Object obj) {
    return (this == obj);
}
复制代码

==表示的是变量值完成相同(对于基础类型,地址中存储的是值,引用类型则存储指向实际对象的地址)
那为什么还有那么多比较==和equals的区别呢? 我们来看几个场景

//这是java.lang.String 中重写之后的equals方法
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
复制代码
//java.lang.Long 中重写之后的equals方法
public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}
复制代码

可以看到,我们经常使用的基本类型,都是重写了equals方法,本质上都是在比较实际值是否相等。
通常情况下 equals表示的是对象的内容完全相同,此处的内容多指对象的特征/属性。我们在重写equals方法的时候也准守这个约定。

protected native Object clone() throws CloneNotSupportedException;

我们可以看到,clone方法是一个本地方法,不是java实现的,是C/C++实现的。 跟其他本地方法可以直接调用不同,这个clone方法不能直接调用,必须实现Cloneable接口。
clone函数返回的是一个引用,指向的是新的clone出来的对象,此对象与原对象分别占用不同的堆空间。

image.png 我们不重写clone方法的情况下,改变了原对象的属性值,不会改变克隆对象的属性值。

public String toString();

源码:

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

默认使用的是类名@hashcode。 toString()方法返回该对象的字符串表示 ,通常我们会重写该方法,输出该对象的一些核心信息。

public final native void notify();

关于wait/notify/notifyAll 这几个方法主要用于java多线程之间的协作.

wait():调用此方法所在的当前线程等待
wait(long timeout)/wait(long timeout, int nanos):调用此方法所在的当前线程等待,直到在其他线程上调用此方法的notisfy()/notisfyAll()方法,或超过指定的超时时间量
notify()/notifyAll():唤醒在此对象监视器上等待的单个线程/所有线程

public final native void notifyAll();

同上

public final native void wait(long timeout) throws InterruptedException;

同上

public final void wait(long timeout, int nanos) throws InterruptedException

同上

public final void wait() throws InterruptedException

同上

protected void finalize() throws Throwable

protected void finalize() throws Throwable { }
复制代码

可以看到,这个方法是一个空方法,没有执行逻辑。 那为什么在Object定义了这个方法呢?是因为所有的对象都有finalize这种行为,在垃圾回收前执行,切不是我们主动调用。

三、面试

比较两个对象是否相等的唯一条件(也是冲要条件)是equals,为啥还要hashcode,这是不是多此一举?

hashCode方法的作用上,其主要用于增强哈希表的性能。

以集合类中,以Set为例,当新加一个对象时,需要判断现有集合中是否已经存在与此对象相等的对象,如果没有hashCode()方法,需要将Set进行一次遍历,并逐一用equals()方法判断两个对象是否相等,此种算法时间复杂度为o(n)。通过借助于hasCode方法,先计算出即将新加入对象的哈希码,然后根据哈希算法计算出此对象的位置,直接判断此位置上是否已有对象即可。(注:Set的底层用的是Map的原理实现)
复制代码

四、思考

猜你喜欢

转载自juejin.im/post/7016599274993483806