Java的Object 类

Java的Object 类是所有类的父类,也就是说 Java 的所有类都继承了 Object,子类可以使用 Object 的所有方法。Object 类位于 java.lang 包中,编译时会自动导入,我们创建一个类时,如果没有明确继承一个父类,那么它就会自动继承 Object,成为 Object 的子类。

classes-object.gif

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

// 显式继承:public class Runoob extends Object{ }复制代码// 隐式继承:public class Runoob { }复制代码Object 类提供的方法

方法 描述Object() 构造一个新对象protected Object clone() 创建并返回一个对象的拷贝boolean equals(Object obj) 比较两个对象是否相等protected void finalize() 当 GC (垃圾回收器)确定不存在对该对象的有更多引用时,由对象的垃圾回收器调用此方法Class<?> getClass() 获取对象的运行时对象的类int hashCode() 获取对象的 hash 值void notify() 唤醒在该对象上等待的某个线程void notifyAll() 唤醒在该对象上等待的所有线程String toString() 返回对象的字符串表示形式void wait() 让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法void wait(long timeout) 让当前线程处于等待(阻塞)状态,直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过参数设置的timeout超时时间void wait(long timeout, int nanos) 与 wait(long timeout) 方法类似,多了一个 nanos 参数,这个参数表示额外时间(以纳秒为单位,范围是 0-999999)。 所以超时的时间还需要加上 nanos 纳秒方法实例:方法实例:

clone() 方法:

protected native Object clone() throws CloneNotSupportedException;复制代码描述:

用于创建并返回一个对象的拷贝。clone 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存。

参数:

返回值:

返回一个对象的拷贝。

注意:

由于 Object 本身没有实现 Cloneable 接口,所以不重写 clone 方法并且进行调用的话会发生 CloneNotSupportedException 异常。

public class Test implements Cloneable {// 声明变量String name;int likes;// 属性引用的对象JueJin jueJin;

Test() {
    this.jueJin = new JueJin();
}

public static void main(String args[]) {
    // 创建对象
    Test obj1 = new Test();

    // 初始化变量
    obj1.name = "Runoob";
    obj1.likes = 111;
    obj1.jueJin.name = "掘金";
    // 打印输出
    System.out.println("obj1 的 name = " + obj1.name); // Runoob
    System.out.println("obj1 的 likes = " + obj1.likes); // 111
    System.out.println("obj1 的 jueJin 的 name = " + obj1.jueJin.name); //掘金

    try {
        // 创建 obj1 的拷贝
        Test obj2 = (Test) obj1.clone();
        obj2.name = "JueJin";
        obj2.likes = 222;
        obj2.jueJin.name = "稀土掘金";
        // 使用 obj2 输出变量
        System.out.println();
        System.out.println("obj2 的 name = " + obj2.name); // JueJin
        System.out.println("obj2 的 likes = " + obj2.likes); // 222
        System.out.println("obj2 的 jueJin 的 name = " + obj2.jueJin.name); //稀土掘金

        System.out.println();
        System.out.println("浅拷贝的问题");
        System.out.println("obj1 的 name = " + obj1.name); // Runoob
        System.out.println("obj1 的 likes = " + obj1.likes); // 111
        System.out.println("obj1 的 jueJin 的 name = " + obj1.jueJin.name); //稀土掘金

    } catch (Exception e) {
        System.out.println(e);
    }
}

}

class JueJin {public String name;}

// 以上程序执行结果为:// obj1 的 name = Runoob// obj1 的 likes = 111// obj1 的 jueJin 的 name = 掘金

// obj2 的 name = JueJin// obj2 的 likes = 222// obj2 的 jueJin 的 name = 稀土掘金

// 浅拷贝的问题// obj1 的 name = Runoob// obj1 的 likes = 111// obj1 的 jueJin 的 name = 稀土掘金复制代码解析:

由于浅拷贝对对象内属性引用的对象只会拷贝引用地址,所以 obj1 与 obj2 的 jueJin 属性引用的对象指向同一内存地址,所以在 obj2 修改 jueJin 的 name 属性后,obj1 的 jueJin 的 name 属性也发生了变化。

equals() 方法:

public boolean equals(Object obj)复制代码描述:

用于比较两个对象是否相等。比较两个对象时,是通过判断两个对象引用指向的是同一个对象,即比较 2 个对象的内存地址是否相等。

参数:

obj -- 要比较的对象。返回值:

如果两个对象相等返回 true,否则返回 false。

注意:

不同的类重写了 equals() 方法,导致equals() 方法的行为有所不同。但如果子类重写了 equals() 方法,就需要重写 hashCode() 方法,比如 String 类就重写了 equals() 方法,同时也重写了 hashCode() 方法。

public class Test implements Cloneable {public static void main(String args[]) {// 创建两个对象Object obj1 = new Object();Object obj2 = new Object();

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

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

}

// 以上程序执行结果为:// false// true复制代码finalize() 方法:

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

用于实例被垃圾回收器回收的时触发的操作。当 GC (垃圾回收器) 确定不存在对该对象的有更多引用时,对象的垃圾回收器就会调用这个方法。

参数:

返回值:

public class Test {public static void main(String args[]) {JunJin junJin = new JunJin();junJin = null;System.gc();}}

class JunJin {@Overrideprotected void finalize() throws Throwable {super.finalize();System.out.println("对象被回收了");}}

// 以上程序执行结果为:// 对象被回收了复制代码getClass() 方法:

public final native Class<?> getClass();复制代码描述:

用于获取对象的运行时对象的类。

参数:

返回值:

返回对象的类。

public class Test {public static void main(String args[]) {// getClass() with ObjectObject 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());
}

}

// 以上程序执行结果为:// obj1 的类为: class java.lang.Object// obj2 的类为: class java.lang.String// obj3 的类为: class java.util.ArrayList复制代码hashCode() 方法:

public native int hashCode();复制代码描述:

用于获取对象的 hash 值。

参数:

返回值:

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

public class Test {public static void main(String args[]) {// Object 使用 hashCode()Object obj1 = new Object();

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

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

    // 获取 obj1 与 obj2 的哈希值
    System.out.println("对象相等则hashCode一定相等");
    System.out.println(obj1.hashCode()); // 225534817
    System.out.println(obj2.hashCode()); // 225534817
}

}

// 以上程序执行结果为:// true// 对象相等则hashCode一定相等// 692404036// 692404036复制代码wait() 方法:

// 该方法有以下几种语法格式:public final void wait() throws InterruptedExceptionpublic final native void wait(long timeout) throws InterruptedExceptionpublic final void wait(long timeout, int nanos) throws InterruptedException复制代码描述:

让当前线程进入等待状态。

参数:

timeout -- 等待超时时间(以毫秒为单位)。如果 timeout 参数为 0,则不会超时,会一直进行等待,类似于 wait() 方法。如果阻塞的时间超过该参数时间,会唤醒线程。

nanos -- 额外时间(以纳秒为单位,范围是 0-999999)。如果设置该时间,超时的时间还需要加上 nanos 纳秒。

返回值:

注意:

当前线程必须是此对象的监视器所有者,否则还是会发生 IllegalMonitorStateException 异常。如果当前线程在等待之前或在等待时被任何线程中断,则会抛出 InterruptedException 异常。如果传递的参数不合法,则会抛出 IllegalArgumentException 异常。notify() 与 notifyAll() 方法:

public final native void notify();复制代码描述:

用于唤醒一个在此对象监视器上等待的线程。如果所有的线程都在此对象上等待,那么只会选择一个线程,选择是任意性的,并在对实现做出决定时发生。

参数:

返回值:

public final native void notifyAll();复制代码描述:

用于唤醒在该对象上等待的所有线程。notifyAll() 方法跟 notify() 方法的区别在于 notifyAll() 方法唤醒在此对象监视器上等待的所有线程,notify() 方法是一个线程。

参数:

返回值:

public class Test {// 声明一个同步列表private List synchedList;

/**
 * 构造方法
 */
public Test() {
    // 创建一个同步列表
    synchedList = Collections.synchronizedList(new LinkedList());
}

/**
 * 删除列表中的元素
 * @return 删除的元素
 * @throws InterruptedException
 */
public String removeElement() throws InterruptedException {
    synchronized (synchedList) {
        // 列表为空就等待
        while (synchedList.isEmpty()) {
            System.out.println("列表是空的...");
            System.out.println("线程 " + Thread.currentThread().getName() + " 将开始等待...");
            synchedList.wait();
            System.out.println("线程 " + Thread.currentThread().getName() + " 等待结束!");
        }
        // 删除元素
        String element = (String) synchedList.remove(0);
        // 返回删除的元素
        return element;
    }
}

/**
 * 添加元素到列表
 * @param element 要添加的元素
 */
public void addElement(String element) {
    synchronized (synchedList) {
        // 添加一个元素,并通知元素已存在
        synchedList.add(element);
        System.out.println("添加了新元素:'" + element + "'");
        synchedList.notify();
        System.out.println("notify 已调用,唤醒 synchedList 上等待的任意一个线程!");
        //synchedList.notifyAll();
        //System.out.println("notifyAll 已调用,唤醒 synchedList 上等待的所有线程!");
    }
    System.out.println("添加元素完成...");
}

/**
 * main 函数
 * @param args
 */
public static void main(String args[]) {
    final Test demo = new Test();

    Runnable runA = new Runnable() {

        public void run() {
            try {
                // 删除 synchedList 中的一个元素并输出
                String item = demo.removeElement();
                System.out.println("删除了元素 " + item);
            } catch (InterruptedException ix) {
                System.out.println("中断的异常!");
            } catch (Exception x) {
                System.out.println("Exception thrown.");
            }
        }
    };

    Runnable runB = new Runnable() {

        // 执行添加元素操作,并开始循环
        public void run() {
            demo.addElement("Hello!");
        }
    };

    try {
        // 创建线程 threadA1 并开始执行
        Thread threadA1 = new Thread(runA, "Google");
        threadA1.start();

        // 当前执行 main 方法的线程休眠
        Thread.sleep(500);

        // 创建线程 threadA2 并开始执行
        Thread threadA2 = new Thread(runA, "Runoob");
        threadA2.start();

        // 当前执行 main 方法的线程休眠
        Thread.sleep(500);

        // 创建线程 threadB 并开始执行
        Thread threadB = new Thread(runB, "Taobao");
        threadB.start();

        // 当前执行 main 方法的线程休眠
        Thread.sleep(1000);

        // 中断 threadA1 线程
        threadA1.interrupt();
        // 中断 threadA2 线程
        threadA2.interrupt();
    } catch (InterruptedException x) {
        System.out.println(x);
    }
}

}复制代码使用 notify() 方法唤醒线程时,可以看到 Google 线程的等待被唤醒了,但 Runoob 线程的等待最终没有被唤醒,输出如下:

列表是空的...线程 Google 将开始等待...列表是空的...线程 Runoob 将开始等待...添加了新元素:'Hello!'notify 已调用,唤醒 synchedList 上等待的任意一个线程!添加元素完成...线程 Google 等待结束!删除了元素 Hello!中断的异常!复制代码使用 notifyAll() 方法唤醒线程时,可以看到 Runoob 与 Google 线程的等待都被唤醒了,但 Runoob 线程唤醒后将集合中的元素删除了,所以集合再次变为空的,Google 就再次进入了等待状态,输出如下:

列表是空的...线程 Google 将开始等待...列表是空的...线程 Runoob 将开始等待...添加了新元素:'Hello!'notifyAll 已调用,唤醒 synchedList 上等待的所有线程!添加元素完成...线程 Runoob 等待结束!删除了元素 Hello!线程 Google 等待结束!列表是空的...线程 Google 将开始等待...中断的异常!复制代码注意:

notify() 与 notifyAll() 方法只能被作为此对象监视器的所有者的线程来调用。如果当前线程不是此对象监视器的所有者的话会抛出 IllegalMonitorStateException 异常。

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

执行对象的同步实例方法使用 synchronized 内置锁对于 Class 类型的对象,执行同步静态方法toString() 方法:

public String toString()复制代码描述:

用于返回对象的字符串表示形式。

参数:

返回值:

返回对象的字符串表示形式。默认返回格式:对象的 class 名称 + @ + hashCode 的十六进制字符串。

public class Test {public static void main(String[] args) {// toString() with ObjectObject obj1 = new Object();System.out.println(obj1.toString());

    Object obj2 = new Object();
    System.out.println(obj2.toString());

    Object obj3 = new Object();
    System.out.println(obj3.toString());
}

}

// 以上程序执行结果为:// java.lang.Object@29453f44// java.lang.Object@5cad8086// java.lang.Object@6e0be858

全部评论

相关推荐

hso_:哈哈哈哈哈哈我没offer一样在同一道题开喷了
投递深圳同为数码等公司10个岗位
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务