public class App1
{
public static void main(String[] args)
{
Point point_1 = new Point(5,5);
Point point_2 = new Point(7,8);
Circle circle_1 = new Circle(point_2, 10);
point_1 = null;
point_2 = null;
}
}
此代码执行后存在多少个对象引用?为什么呢?
答案 0 :(得分:7)
此代码执行后,完全没有,因为它将退出: - )
如果你的意思是在退出前的那一点上,假设构造函数存储它,则在你的圆圈上有一个参考,你的圆圈中有一个参考到第二个点。
答案 1 :(得分:7)
尽管存在配方问题,但该片段在垃圾收集的某些方面实际上非常有启发性。让我们逐行看一下。
Point point_1 = new Point(5,5);
所以我们声明了一个引用变量point_1
,它指向new Point
。我们现在假设Point
的构造函数没有做任何奇特的事情,只需使用给定的值设置字段final int x, y
。
因此,我们现在有这样的事情:
现在让我们来看看下一行:
Point point_2 = new Point(7,8);
现在我们有这样的事情:
现在让我们来看看下一行:
Circle circle_1 = new Circle(point_2, 10);
我们再次不知道Circle
是如何实现的,但假设它有final Point center
和final int radius
字段以及Point center
是合理的具体来说,它只是设置对给定Point
的引用(即没有防御性复制,因为Point
是不可变的)。
所以现在我们可能会有这样的事情:
然后在接下来的两个语句中,我们将point_1
和point_2
分别指向null
:
point_1 = null;
point_2 = null;
所以现在我们有这样的事情:
我们现在可以观察到:
[aPoint(5 5)]
[aPoint(7 8)]
虽然不再由point_2
引用,但仍由[aCircle(10)].center
引用。垃圾收集性是由实时引用是否可以访问对象来定义的。对象[aPoint(5 5)]
,我们可以强烈假设(基于我们认为Point
的实现方式),不再可以访问,因此它有资格进行收集(这是一个垃圾!没有人可以“捡起它” “现在!)。
另一方面,对象[aPoint(7, 8)]
仍由[aCircle(10)].center
引用,因此我们可以说它 NOT 有资格收集(它不是垃圾!有人仍然“坚持”它!)。
所以不,绝对设置对null
的引用确实 NOT 使之前被引用的对象自动符合收集资格。它取决于对象本身,是否有对该对象的引用。
当然,设置对null
CAN 的引用有助于使对象有资格进行收集,例如:当该引用是对象的最后剩余时间。
您执行 NOT 但是,必须始终设置对null
的引用以使垃圾收集“正常”。当变量超出范围时,引用不再存在,因此在明确设置为null
的情况下,这只是冗余代码。
明确设置为null
DOES 工作的典型示例是Stack
示例:当从Stack
弹出顶部元素时,{{ 1}}不应再从其内部数据结构中引用该对象。
答案 2 :(得分:5)
答案是:
Point
和Circle
类的详细信息,就无法知道甚至创建了多少个对象引用。main
方法退出后,没有任何对象可以访问...引用是否仍然“存在”。我们可能会推断,在main
方法返回之前的某个时间点,将有一个对Circle
对象的可访问引用和一个对Point
的可访问引用。但是必须对这两个类如何实现以进行推断做出一些(合理的)假设。 (例如,必须假设相应的构造函数不会将Point
和Circle
引用添加到某些静态数据结构中。)
当对象的引用被清空时是否清理了对象?
没有。垃圾收集器运行时会清除对象,并确定无法再访问相关对象。从这个意义上讲,“可达”意味着您可以通过从对象开始跟随对象链来访问该对象:
(我已经简化了GC和可达性的解释,以避免将OP与他/她还不会理解的东西混淆。)