PDF 课件和源代码下载地址:
https://gitee.com/geektime-geekbang/LetsJava
作者回复: 这个作为初学的内容,是有点超纲了。SoftReference,WeakReference和PhantomReference首先是一个类,并不是一个Java的基本数据类型。这三个更多的是和 Java 的垃圾回收相关。如果是你在准备面试,可以研究一下,如果是平时工作使用,建议谨慎使用。这三个类的Javadoc对它们的特性解释的比较清楚了。 简单来说,soft是能不回收就不回收,适合做cache,weak是能回收就回收,如果没有别的正常引用指向一个对象,只有weak的reference,那就回收。PhantomReference就直接不能使用,只是用来影响finalize方法。 总结一下,这三种引用,我的建议是,能不用就不用。
作者回复: ✅
作者回复: 补充完整一下, 避免歧义: 如果是基本类型,那么这块地址“对应的内存里”的值就是这个基本类型的值;如果是引用类型,那么这块地址“对应的内存里”存储的“值”是堆中这个实例的地址。
作者回复: 正好顺手把FAQ搬到InfoQ写平台。你可以先看看这篇Java内存分布的文章。 https://xie.infoq.cn/article/38f5ad03242b79b46e30bfa1b 回到你的问题,简单来说,这里面有个编译,链接的过程。不能简单的认为int a就直接被计算机映射到一个内存地址。首地址和类型信息都是在编译和链接的时候确定的。 Java是无法单独给int a分配内存的。要么在堆上,比如说是某个对象的成员属性。要么在栈上,比如说是某个局部变量(或者参数)。 其实我们看到的int a,实际上地址并不是直接存储的。如果你有幸没有学过汇编(我不是开玩笑的),那么我告诉你我也忘的差不多的一点汇编知识。计算机在寻址(寻找内存的地址)时,有很多种方式,比如基址变址寻址,就是在一个基本地址之上,加上一个偏移量。 假设a是一个对象m的一个成员变量。我们知道m是个引用,保存着对象的地址。那么m.a就是在m这个对象地址的基础上(基址),加上一个偏移量(变址),就找到a的地址啦。(注意:汇编忘记的差不多了,大概是这么个意思不会错的。) 至于a的类型,以及加上的偏移量是多少,这些都是在编译和链接的过程中确定的。也就是说,我们写代码写的是m.a,而编译链接之后,在执行的时候: 我们写的m.a,就 = 计算机的:m这个地址,再加上128,从这个地址取出4个连续的字节,当作是个int。 你也可以认为这就是编译器和链接做的事情,把我们的m.a翻译成了后面计算机执行的这几个连续动作。 如果a是个局部变量,那么过程也差不多。当然,Java虚拟机有很多个字节码就是用来操作局部变量的,进栈出栈(push,pop)什么的,过程更曲折一点。。简单来说,编译和链接之后执行的代码,只是完成了我们源代码所让其完成的操作,但是过程要复杂很多。 写的太好了,加到我的FAQ里去。
作者回复: ✔,你get了~!
作者回复: 我理解你的问题是对象被多次引用,而不是类。不会的,一个对象无论被多少引用引着,都只有一个
作者回复: 对头,就是这么跳。简单来说,一个点就是跳一次。 m1.factory.address.street 就是从m1跳到factory,再跳到address,再跳到street
作者回复: 慈祥…… 好吧,等我拿我的保温杯泡一杯枸杞茶。
作者回复: Java里只有引用,没有指针哦。Java只有几种基本数据类型(比如jint,long,boolean这些),以及引用类型。传递就是赋值一份。
作者回复: 隔着屏幕都能感觉到满满的学习的满足感