为了账号安全,请及时绑定邮箱和手机立即绑定

Java基础学习之--理解Object类

标签:
Java


看Java API的Object类, 一共11个方法。按使用的频度排名:

toString() 这个方法最常用在打日志,定位代码问题。

equals()和hashCode(), 这两个方法的使用经典例子是HashMap的源码

    public V put(K key, V value) {

        if (table == EMPTY_TABLE) {

            inflateTable(threshold);

        }

        if (key == null)

            return putForNullKey(value);

        int hash = hash(key);

        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {

            Object k;

            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

                V oldValue = e.value;

                e.value = value;

                e.recordAccess(this);

                return oldValue;

            }

        }

        modCount++;

        addEntry(hash, key, value, i);

        return null;

    }

equals() 比 hashCode() 要常用一点。

wait() 和 notify() 这个开发很少会直接用到,但是间接用到的场景不少,属于偏内功的点。wait/notify属于Object类最难理解的点了,因为它的基石是多线程。学习思路还是三步走。

step 1: 看文档说明

wait()

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.

notify()

Wakes up a single thread that is waiting on this object's monitor.

这个文档说明,看完基本一头雾水,两个方法都提到了如下的核心概念thread, object's monitor。 先把这些概念放一边,看看是怎么用的。

step 2: 运行Demo

给个demo辅助理解,一个线程是干活的,另一个线程是管事的。管事的等活干完验收。

public class WaitNotifyDemo {

    static class Worker extends Thread{

        private volatile int status=0; // 1: 完成, -1: 出错

        @Override

        public void run(){

            try {

                System.out.println(Thread.currentThread().getName() +": 开始干活");

                Thread.sleep(3000);

                System.out.println(Thread.currentThread().getName() +": 完成任务");

                status = 1;

                // 通知主线程

                synchronized (this){

                    this.notify();

                }

            } catch (InterruptedException e) {

                e.printStackTrace();

                status = -1;

            }

        }

        public int getStatus(){

            return status;

        }

    }

    public static void main(String[] args) throws InterruptedException {

        Worker worker= new Worker();

        worker.start();

        synchronized (worker){

            int status;

            while ((status=worker.getStatus())!=1){

                worker.wait();

                if(status==-1)

                    throw new RuntimeException("出错了");

            }

        }

        System.out.println("任务已经完成");

    }

}

step3: 折腾demo

接下来, 我试了一下, 把notify的代码去掉,也能正常运行。 这就让人困惑了,文档明明说必须调用notify,wait才能结束。接下来再看文档:

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup

所以, wait方法必须在while循环中调用。好,解答了一点疑惑。但是每次Worker线程结束时没有调用notify,主线程就能正常退出, 这个也说不通。 唯一的解释是: JVM内部在某个地方调用了notify。看openjdk的源码, 果然如此:从start0开始, 定位到线程在退出时会调用lock.notify_all(thread);。只是这里的代码是JVM内部的代码,比较底层。

其实,这个例子更简洁的写法是worker.join()。 如果看Thread.join()的源码,发现它的实现恰好就是调用了wait。

clone() 这个需要理解深度克隆, 知识点不复杂。

getclass() 这个放在后面,但是用得还挺多的,特别是写框架。

finalize() 这个已经不他推荐使用了, 尽量不干扰GC的节奏。

总结一下,Object类是Java的基石。这里比较难一点的就是wait/notify. 学习Java的API, 如果想理解透彻一点,估计绕不开JVM的c++源码。

©著作权归作者所有:来自51CTO博客作者sbp810050504的原创作品,如需转载,请注明出处,否则将追究法律责任


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消