所有类的父类 Java Object

Java Object

一、什么是Java Object

Java Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。(得了,就是Object就是所有类的爸爸)

Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。

Object 类可以显示继承,也可以隐式继承,以下两种方式时一样的:

显示继承:

public class Test extends Object{

}

隐式继承:

public class Test{

}

下面我们来分析一下Object的源码:

package java.lang;

public class Object {

    private static native void registerNatives();
    static {
        registerNatives();
    }
    
   //获取对象的运行时对象的类
    public final native Class<?> getClass();
    
   //获取对象的 hash 值 
    public native int hashCode();
    
    //比较两个对象是否相等
    public boolean equals(Object obj) {
        return (this == obj);
    }
    
    //创建并返回一个对象的拷贝
    //clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。
    //浅克隆复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,克隆之后的对象和之前的对象仍存在一些关联,克隆程度不高,因此也被称为浅克隆。
//而深克隆复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。
    protected native Object clone() throws CloneNotSupportedException;

   //返回对象的字符串表示形式
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
   //唤醒在该对象上等待的某个线程
    public final native void notify();

    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);
    }

    public final void wait() throws InterruptedException {
        wait(0);
    }
   //当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法。
    protected void finalize() throws Throwable { }
}

二、Object类的方法

1、创建并返回一个对象的拷贝protected Object clone()

**
 * @Description: $ clone()案例
 * @Author: dyq
 * @Date: $2021年2月4日
 */
public class CloneTest implements Cloneable {

    // 声明变量
    String name;
    int age;

    public static void main(String[] args) {

        // 创建对象
        CloneTest obj1 = new CloneTest();

        // 初始化变量
        obj1.name = "科隆";
        obj1.age = 20;

        // 打印输出
        System.out.println(obj1.name); // 科隆
        System.out.println(obj1.age); //20

        try {
            // 创建 obj1 的拷贝
           CloneTest obj2 = (CloneTest) obj1.clone();

            // 使用 obj2 输出变量
            System.out.println("clone后:");
            System.out.println(obj2.name); // 科隆
            System.out.println(obj2.age); //20
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

结果输出:

科隆
20
clone后:
科隆
20

clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。
那么浅克隆跟深克隆有什么区别?
浅克隆复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说,克隆之后的对象和之前的对象仍存在一些关联,克隆程度不高,因此也被称为浅克隆。
而深克隆复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

2、比较两个对象是否相等 boolean equals(Object obj)

Object equals() 方法用于比较两个对象是否相等

equals() 方法比较两个对象,是判断两个对象引用指向的是同一个对象,即比较 2 个对象的内存地址是否相等。

注意:如果子类重写了 equals() 方法,就需要重写 hashCode() 方法,比如 String 类就重写了 equals() 方法,同时也重写了 hashCode() 方法。

该方法返回值为布尔型,则如果两个对象相等返回 true,否则返回 false。

案例:

/**
 * @Description: equals()案例$
 * @Author: dyq
 * @Date: 2021年2月4日$
 */
public class equalsTest {
    public static void main(String[] args) {
        // Object 类使用 equals() 方法
        // 创建两个对象
        Object obj1 = new Object();
        Object obj2 = new Object();

        // 判断 obj1 与 obj2 是否相等
        // 不同对象,内存地址不同,不相等,返回 false
        System.out.println(obj1.equals(obj2)); // false

        // obj1 赋值给 obj3
        // String 重写了 equals() 方法
        // 对象引用,内存地址相同,相等,返回 true
        Object obj3 = obj1;
        System.out.println(obj1.equals(obj3)); // true



        // String 类使用 equals() 方法
        // 创建两个对象
        String obj4 = new String();
        String obj5 = new String();

       // 判断 obj4 与 obj5 是否相等
        // 初始化的两个对象都为 null,所以是相等,返回 true
        System.out.println(obj4.equals(obj5)); // true

        // 给对象赋值
        obj4 = "哥哥";
        obj5 = "哥";

        // 判断 obj4 与 obj5 是否相等
        // 两个值不同,内存地址也不同,所以不相等,返回 false
        System.out.println(obj4.equals(obj5)); // false
    }
}

结果:

false
true
true
false

3、当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此finalize() 方法。

Object finalize() 方法用于实例被垃圾回收器回收的时触发的操作。

在GC准备释放对象所占用的内存空间之前,它将首先调用finalize()方法

finalize()方法中一般用于释放非Java 资源(如打开的文件资源、数据库连接等),或是调用非Java方法(native方法)时分配的内存。

4、获取对象的运行时对象的类 Class<?> getClass()

Object getClass() 方法用于获取对象的运行时对象的类。
示例:

/**
 * @Description: $getClass
 * @Author: dyq
 * @Date: $
 */
public class getClassTest {

    public static void main(String[] args) {

        // getClass() with Object
        Object obj1 = new Object();
        System.out.println("obj1 的类为: " + obj1.getClass());

        // getClass() with String
        String obj2 = new String();
        System.out.println("obj2 的类为: " + obj2.getClass());

        // getClass() with ArrayList
        ArrayList<Integer> obj3 = new ArrayList<>();
        System.out.println("obj3 的类为: " + obj3.getClass());

        // 创建 getClassTest 类的对象
        getClassTest classTest = new getClassTest();
        // getClassTest 继承 Object 类,Object 是所有类的超类
        // 调用 getClass() 方法
        System.out.println("classTest的类为:"+classTest.getClass());
    }
}

结果:

obj1 的类为: class java.lang.Object
obj2 的类为: class java.lang.String
obj3 的类为: class java.util.ArrayList
classTest的类为:class com.Colltion.Test.getClassTest

5、获取对象的 hash 值 int hashCode()

返回对象是哈希值,是一个整数,表示在哈希表中的位置。

示例:

import java.util.ArrayList;

/**
 * @Description: $hashCode()
 * @Author: dyq
 * @Date: $
 */
public class hashCodeTest {
    public static void main(String[] args) {

        // Object 使用 hashCode()
        Object obj = new Object();
        System.out.println(obj.hashCode());

        //String 和 ArrayList 类都继承了 Object,所以可以直接使用 hashCode() 方法:

        // String 使用 hashCode()
        String str = new String();
        System.out.println(str.hashCode()); // 0

        // ArrayList 使用 hashCode()
        ArrayList<Integer> list = new ArrayList<>();
        System.out.println(list.hashCode()); // 1

        //如果两个对象相等,则它们的哈希值也是相等的
        // Object 使用 hashCode()
        Object obj1 = new Object();

        // obj1 赋值给 obj2
        Object obj2 = obj1;

        // 判断两个对象是否相等
        System.out.println(obj1.equals(obj2)); // true

        // 获取 obj1 与 obj2 的哈希值
        System.out.println(obj1.hashCode()); // 1163157884
        System.out.println(obj2.hashCode()); // 1163157884
    }
}

结果:

460141958
0
1
true
1163157884
1163157884

6、唤醒在该对象上等待的某个线程void notify()

notify() 方法只能被作为此对象监视器的所有者的线程来调用。

一个线程要想成为对象监视器的所有者,可以使用以下 3 种方法:

  1. 执行对象的同步实例方法
  2. 使用 synchronized 内置锁
  3. 对于 Class 类型的对象,执行同步静态方法

一次只能有一个线程拥有对象的监视器。

如果当前线程不是此对象监视器的所有者的话会抛出 IllegalMonitorStateException 异常。

上一篇:JS判断一个对象是不是数组类型,一共有7种方式


下一篇:this的指向