JDK源码——java.lang

前段时间开始看了一下java.lang的部分源码,但因这部分东西比较琐碎无法形成系统的文档,因此一直没有记录下来,但后来一想,就算琐碎也还是记录下来的好,就当给自己的进步留下一点痕迹,如果给自己和其他同学一点启示那就更好了


先聊一下三个最常见的类:StringBuffer,StringBuilder,String
StringBuffer与StringBuilder,他们两个有共同的父类AbstractStringBuilder,且其API基本一致,区别是StringBuffer的每个类都用synchornized修饰,故是线程安全的
String,大家都知道String是不可变的,因此如果有频繁的字符串操作,则不应该用String,但为什么String是不可变的?可能这个就不清楚了,下面让源码来说话
这里写图片描述
String中最重要的两个属性就是value[]和hash,value中存储的是String的字符,如String str = new String(“abc”),此时value={‘a’,’b’,’c’};hash是字符串的hashcode,与此处讨论的String为什么不变没有联系暂时不讨论.
可以看到value属性是private的,且没有提供setValue方法,因此从外部来说是不可变的;再者value被final修饰过因此String内部是无法修改的
再来看String中的一下方法,比如replace
这里写图片描述
这里直接返回了一个新的字符串.OK到这里应该明白String为什么不可变了.
String这里还有一个知识点可以带着讲一下,那就是==、equals和hashcode
==和equals的区别我不说了,如果不了解我觉得你离看源码还有点距离
咱们来说一下equals和hashcode,相信大家都知道重写equals必须重写hashcode,但为什么呢?有些同学可能背过:相同的对象必须具有相同的hashcode,但这又是为什么呢?或者说如果相同的对象有不同的hashCode会有什么问题呢?我的思路是这样的:
首先如何保证两个对象相等?没错咱们要重写equals;这时逻辑上是相等了,这时我们把这两个逻辑相等的对象保存在同一个set中,但这时set的size会是2而不是我们预想的1,因为Set认为同一个对象hashcode必须相同,因此我们我们才必须重写hashcode方法


注:同一对象的hashcode必须相同,但hashcode相同的未必是同一对象
注**:Object中HashCode代表对象内存地址,HashCode相同一定是同一对象;但如果重写了,因算法问题可能导致上面的情况
因此我们无法用HashCode来比较两个对象是否相同,但可以用HashCode来比较两个对象是否不同;比较两个对象是否相同必须用equals


class、classLoader等类因很多方法都是c++实现,java中看不了,因此收获不大


Object:
ps.源码中的注释都是英语的,我怕自己的理解不够准确,因此我贴出了jdk的中文版的解释(删除了翻译中我觉得冗余的部分)

notify():唤醒在此对象监视器上等待的单个线程.如果所有线程都在此对象上等待,则会选择唤醒其中一个线程.选择是随机的.线程通过调用其中一个wait()方法,在对象的监视器上等待.
直到线程放弃此对象上的锁定(也就是说wait()会释放对象锁),才能继续执行被唤醒的线程.被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;即唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。

此方法只应由作为此对象监视器的所有者的线程来调用.通过以下三种方法,线程可以成为此对象监视器的所有者:

  • 通过执行此对象的同步实例方法.
  • 通过执行在此对象上进行同步的 synchronized 语句的正文.
  • 对于 Class 类型的对象,可以通过执行该类的同步静态方法.

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


notifyAll():唤醒在此对象监视器上等待的所有线程.其他都和notify()一致


wait():在其他线程调用此对象的notify()方法或notifyAll()方法,或者超过指定的时间量前,导致当前线程等待。
当前线程必须拥有此对象监视器(notify()方法中有讲怎么获取对象监视器).
唤醒线程的四种方式:

  • 其他某个线程调用此对象的 notify 方法,并且当前线程被选为被唤醒的线程
  • 其他某个线程调用此对象的 notifyAll 方法
  • 其他某个线程中断当前线程
  • 已经到达指定的实际时间.(如果 timeout 为零,则不考虑实际时间,在获得通知前该线程将一直等待)

一旦获得对该对象的控制权,该对象上的所有其同步声明都将被恢复到以前的状态,也就是说从wait方法返回时,该对象和当前线程的同步状态与调用wait方法时的情况完全相同

在没有被通知、中断或超时的情况下,线程还可以唤醒一个所谓的虚假唤醒 (spurious wakeup).虽然这种情况在实践中很少发生,但是应用程序必须通过以下方式防止其发生,即对应该导致该线程被提醒的条件进行测试,如果不满足该条件,则继续等待.换句话说.wait()应总是发生在循环中

由于wait()方法将当前线程放入了对象的等待集中,所以它只能解除此对象的锁定(也就是说wait()会释放对象锁)

equals():Object中判断两个对象是否相等就是用==,文章上面有详细写到equals()、==、hashCode()的更多内容

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

贼重要的一个类Thread,这个类里面要聊的方法比较多,我简单说一下,就不把源码的解释贴上来了
interrupt():线程中断,调用此方法会让线程中断
这里写图片描述
join():等待线程结束在运行下面的程序,join()的本质是判断一个是否正在运行,如果正在运行就wait(),如果不在运行就往下执行
这里写图片描述
yield():线程谦让,让出cup执行时间,然后让其他线程可以参与cpu执行时间的竞争
还有一些其他操作如stop()、suspend()、resume()等方法也挺重要,但是他们都是不推荐使用的方法,因此我在这里也不做介绍了


今天先到这,下次继续写

ps.我预感这会是一篇极其极其极其极其长的博客

顺便说一下我要看的jar包,有同学有兴趣一起看的话,可以一起学习:
java.io
java.lang
java.util
java.lang.reflect
java.net
javax.net.*
java.nio.*
java.util.concurrent.*
ps:这里面的异常包我没看过,也不准备看~~~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值