2

我的疑问是引用玫瑰对象的引用变量“r”现在正在引用花对象。

玫瑰对象现在怎么了?会被摧毁吗?

我有以下代码:

class Flower
{
public void smell()     // I
{
   System.out.println("All flowers give smell, if you can smell");
}
}   
public class Rose extends Flower
{
public void smell()     // II
{
   System.out.println("Rose gives rosy smell");
}
public static void main(String args[])
{
   Flower f = new Flower();
   Rose r = new Rose();

   f = r;             // subclass to super class, it is valid
   f.smell();           // II

 }
}
4

5 回答 5

9

在此处输入图像描述

Flower是符合垃圾收集条件的对象。Rose 对象仍然由两个引用变量引用,即fr

于 2013-05-21T11:01:30.287 回答
4

在这里,您已将玫瑰分配给f变量。这意味着花的实例现在可以被销毁(垃圾收集)。

f包含玫瑰,所以f.smell()会导致Rose gives rosy smell.

于 2013-05-21T11:02:05.390 回答
2

在您的代码中,未使用的实例f = new Flower()最终将被删除(意味着您无法再解决它,垃圾收集很可能会在将来的某个时候将其删除)。

对于以下代码,这将是相同的:

Rose one = new Rose();
Rose two = new Rose();
one = two;

one = new Rose()变量不会被使用,最终将被删除。因此,这首先与铸造无关。

Rose由于您可以将所有对象作为Flower对象来寻址,因此您可以将Rose实例分配给Flower变量。

于 2013-05-21T11:01:28.363 回答
1

如果它被创建为新的玫瑰,它永远是玫瑰,铸造不会影响底层对象。然而某些方法并不关心它是否是一朵玫瑰,只是它是某种花,他们以一朵花作为他们的论据,玫瑰被视为任何旧花(但可以重新变成一朵玫瑰)。

同样在您的情况下,您有花变量 f,玫瑰是一朵花,因此玫瑰可以包含在花变量中,但它基本上仍然是玫瑰。

同样,作为新花创建的对象永远不会是玫瑰,转换为玫瑰不会导致编译时异常,因为花可能是玫瑰,但会引发运行时异常,因为在这种情况下它不是。

正如其他答案正确地说的那样,您的“新花”从未使用过,将被垃圾收集

于 2013-05-21T11:07:37.403 回答
1

运行以下代码时:

 Flower f = new Flower();//Line1
 Rose r = new Rose();//Line2
 f = r;   //Line3

这就是发生的事情:

Line1在堆内存上创建一个新的 Flower 对象,引用 f 将在堆栈上。

Line2在堆内存上创建一个新的 Rose 对象,引用 r 将在堆栈上。

Line3现在分配 f=r 使 f 也成为对 line2 中创建的同一个 Rose 对象的引用,因此对在 line1 处创建的花对象的引用将丢失,因此花对象将在堆内存中保持未引用,直到它被JVM收集并最终销毁的垃圾。

于 2013-05-21T11:17:02.297 回答