Object对象及方法详解(Object必学篇)

书欣 Java教程 发布时间:2022-09-30 22:32:36 阅读数:15149 1
下文笔者讲述Object对象及方法的详解说明,如下所示

Object简介

Object类是所有类的超类,所有类都默认继承Object
 所以我们必须彻彻底底的弄清楚Object的点点滴滴 

注意事项:
    数组也会继承Object类中的方法 

Object之wait

public final native void wait(long timeout) throws InterruptedException;
       Object的wait方法被设计为子类不可重写(Override)
	    此方法采用native修饰,是JVM提供的方法

wait:
   当调用wait时,当前线程持有对象的监视器(锁)
   当前线程获取到对象锁后
   调用此方法将导致当前的线程释放当前的对象锁并且让出cpu资源
   当前线程进入阻塞状态(等待),直到其他线程调用此对象的notify()方法或notifyAll()方法唤醒或超过指定的时间量

注意事项:
   当前线程不是锁的持有者(未被监视)
   调用该方法抛出一个IllegalMonitorStateException异常
例:
package com.java265;
public class TestClass {
    public static void main(String[] args) throws InterruptedException {
        TestClass obj = new TestClass();
        obj.wait(10);
    }
}

此时抛出异常
Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at cn.lovecto.test.TestClass.main(TestClass.java:5)

注意事项:
   调用wait方法只能在同步代码块或同步方法中
正确的写法
synchronized (obj) {
    while (<condition does not hold>)
        obj.wait(timeout);
    ... // Perform action appropriate to condition
}
Object中除了native的wait方法,还有另外两个wait方法,他们的内部实现都是基于native的wait方法的,只是阻塞时间上的差异。

public final void wait() throws InterruptedException {
    wait(0);
}
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);
}
注意事项:
   当设置的时间为0时
     线程只会等待其他线程通过notify()方法或notifyAll()方法唤醒
      否则一直阻塞下去
   当设置的时间大于0
    如果过了等待时间,此时对象锁被其他线程持有,当前线程也会继续等待

当一个线程被wait时,如果需继续执行,必须满足以下任一条件
   1.由其他线程notify或notifyAll,且当前线程被通知,和其他线程进行锁竞争,成功获取锁
   2.没有被notify或notifyAll通知到,但过了wait超时时间和其他线程进行锁竞争,成功获取锁

Object中notify、notifyAll

注意事项:
    Object中notify,notifyAll是不可被子类覆盖
	并且两个方法都是native 
public final native void notify();
   调用notify方法将唤醒在此对象监视器上等待的单个线程
   如果所有线程都在此对象上等待,则会选择唤醒其中一个线程
    此种选择是任意性的。
   线程通过调用其中一个wait方法,在对象的监视器上等待,
    直到当前的线程放弃此对象上的锁定,才能继续执行被唤醒的线程
	被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争
	 所以notify会随机选择一个在该对象上调用wait方法的线程,解除其阻塞状态,该方法只能在同步方法或同步块内部调用,
	 如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
 
public final native void notifyAll();
     notifyAll会解除所有那些在该对象上调用wait方法的线程的阻塞状态
    该方法只能在同步方法或同步块内部调用
     如果当前线程不是锁的持有者,该方法抛出一个IllegalMonitorStateException异常。
例:
package com.java265;

import java.util.Linkedlist;
import java.util.List;
public class ProducerStorageConsumer {

    /** 仓库 */
    static class Storage {
        /** 仓库最大容量 */
        private int maxSize;
        /** 仓库容器 */
        private List<Object> storage;

        public Storage(int maxSize) {
            super();
            this.maxSize = maxSize;
            this.storage = new LinkedList<Object>();
        }

        /**
         * 向仓库中添加产品
         * 
         * @param object
         */
        public synchronized void add(Object object) {
            // 仓库容量满了,生产者暂停生产
            while (storage.size() == maxSize) {
                try {
                    wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            // 生产者添加产品到仓库,通知所有消费者获取产品
            storage.add(object);
            System.out.printf("添加产品到仓库,当前库存: %d: %s\n", storage.size(), object);
            notifyAll();
        }

        /**
         * 消费者从仓库中获取产品
         * @return
         */
        public Object get() {
            Object object = null;
            synchronized (this) {
                //产品库存空了,消费者暂停消费
                while(storage.size() == 0) {
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                object = ((LinkedList<Object>)storage).poll();
                System.out.printf("从仓库获取产品,剩余库存: %d: %s\n", storage.size(), object);
                notifyAll();
            }
            return object;
        }
    }

    /**生产者*/
    static class Producer implements Runnable{
        /**消费者名称*/
        private String name;
        /**生产者产量*/
        private int num;
        /**仓库库存*/
        private Storage storage;

        public Producer(String name, int num, Storage storage) {
            super();
            this.name = name;
            this.num = num;
            this.storage = storage;
        }

        @Override
        public void run() {
            for(int i = 1; i <= num; i++){
                storage.add(name + "生产的第" + i + "个产品");
            }
        }
    }

    /**消费者*/
    static class Consumer implements Runnable{
        /**消费者消费量*/
        private int num;
        /**仓库库存*/
        private Storage storage;

        public Consumer(int num, Storage storage) {
            super();
            this.num = num;
            this.storage = storage;
        }

        @Override
        public void run() {
            for(int i = 0; i < num; i++){
                Object object = storage.get();
                System.out.println("取走了" + object);
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        Storage storage = new Storage(2);
        Producer producer = new Producer("生产者" , 10, storage);
        Thread thread1 = new Thread(producer);
        Consumer consumer = new Consumer(10, storage);
        Thread thread2 = new Thread(consumer);
        thread2.start();
        thread1.start();
        Thread.sleep(1000);
    }
}

Object之hashCode

Object的hashCode方法默认实现是native的
  返回的是对象的地址
  hashCode是可以被重写覆盖

注意事项:
    重写了equals方法的类,都必须覆盖hashCode方法
	因为不覆盖hashCode会违反一些类的设计准则

Object中equals

Object之equals方法:
   默认实现是比较对象的引用是否指向同一个对象
   equals可以被子类重写覆盖

默认equals比较原理:
    对于对象引用,==比较对象引用是否指向同一个对象。对于基本类型,比较实际内容。

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

equals应用场景

当需要编写自己的比对逻辑时
此时我们需重写equals方法

Object中clone

Object的clone的作用是创建并返回此对象的一个副本
 方法时native的
 此方法可被子类重写覆盖

protected native Object clone() throws CloneNotSupportedException; 
  当类未实现接口Cloneable,则会抛出CloneNotSupportedException

注意事项:
   1.此方法是该对象的“浅复制”,而不“深复制”操作
       浅拷贝:对于基本数据类型,复制其数据。对于对象引用,只是复制对象引用,而不是复制对象引用所指向的对象
   2.由于Object类本身未实现接口Cloneable,所以在类为Object的对象上调用clone方法将会导致在运行时抛出异常

Object之toString

Object之toString方法的功能:
    用于返回该对象的字符串表示
Object类的toString方法返回一个字符串
  该字符串由类名(对象是该类的一个实例)、at标记符“@”和此对象哈希码的无符号十六进制表示组成

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

Object之finalize

Object的finalize方法主要用于垃圾回收
   此方法可以被子类重写覆盖。

protected void finalize() throws Throwable { }
   当垃圾回收器确定不存在对该对象的更多引用时
   由对象的垃圾回收器调用此方法
   子类重写finalize方法,以配置系统资源或执行其他清除
   该方法的执行通常是不可预测的,也非常危险的,笔者不推荐大家使用
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

本文链接: https://www.Java265.com/JavaCourse/202209/4548.html

最近发表

热门文章

好文推荐

Java265.com

https://www.java265.com

站长统计|粤ICP备14097017号-3

Powered By Java265.com信息维护小组

使用手机扫描二维码

关注我们看更多资讯

java爱好者