Java 在此示例中,有多少对象符合垃圾收集器的条件

Java 在此示例中,有多少对象符合垃圾收集器的条件,java,garbage-collection,Java,Garbage Collection,当m()退出时,我统计了5个符合垃圾收集器条件的元素。练习说6是正确答案。您能帮助我吗?对getCurrency()的两个调用将总共创建两个Currency对象。每次通话需要: 一个整数对象作为参数,随后分配给值 货币对象 名称字符串对象(不是静态,即每个货币对象都有一个) 3×2=6 更新: 最大的问题似乎是,是否会为对Currency构造函数的每次调用创建一个新的Integer对象。将原语int自动装箱为Integer将调用Integer.valueOf()。关于Integer.valu

m()
退出时,我统计了5个符合垃圾收集器条件的元素。练习说6是正确答案。您能帮助我吗?

getCurrency()
的两个调用将总共创建两个
Currency
对象。每次通话需要:

  • 一个
    整数
    对象作为参数,随后分配给
  • 货币
    对象
  • 名称
    字符串对象(不是
    静态
    ,即每个
    货币
    对象都有一个)
3×2=6

更新:

最大的问题似乎是,是否会为对
Currency
构造函数的每次调用创建一个新的
Integer
对象。将原语
int
自动装箱为
Integer
将调用
Integer.valueOf()
。关于
Integer.valueOf()
,有这样的说法:

返回表示指定int值的整数实例。如果不需要新的整数实例,通常应优先使用该方法而不是构造函数整数(int),因为通过缓存频繁请求的值,该方法可能会产生显著更好的空间和时间性能此方法将始终缓存-128到127(含)范围内的值,并可能缓存此范围以外的其他值。


因此-128到127范围内的值会被缓存。但问题是,在代码中,您使用的是两个不同的值50和100,因此缓存不会避免创建新的
整数
对象AFAIK。

我不同意公认的答案。我相信你关于五个对象符合垃圾收集条件的回答实际上是正确的,而你所做的练习是错误的(尽管如果有人能解释我的错误,我将不胜感激)

以下是程序引用的对象:

  • Integer
    #0-由
    static Integer value=new Integer()创建的
    Integer
    *
  • Currency
    #1-由
    Currency.getCurrency(50)
    创建的
    Currency
  • Integer
    #1-自动装箱
    50
    返回的
    Integer
  • String
    #1-由
    Currency
    #1中的
    String name=new String()
    创建的
    字符串
  • Currency
    #2-由
    Currency.getCurrency(100)
    创建的
    Currency
  • Integer
    #2-自动装箱
    100
    返回的
    Integer
  • String
    #2-由
    Currency
    #2的创建中的
    String name=new String()
    创建的
    字符串
  • *这实际上并没有编译,但我假设它被有效的代码替换,否则不会影响程序


    因此,代码运行需要七个对象。当
    value
    50
    覆盖时,
    value
    最初引用的对象将有资格进行垃圾收集。第一个和第二个
    Currency
    s在
    m
    结束时符合条件,因为它们的唯一引用超出了范围。当第一个和第二个
    字符串
    s的唯一引用对象
    Currency
    s1和2超出范围时,它们在
    m
    的末尾符合条件。来自
    100
    的自动装箱的
    Integer
    在最后仍然被静态引用
    引用,因此不符合垃圾收集的条件。有5个对象符合条件,1个不符合条件,还有一个尚未讨论

    最后一个对象是
    50
    的自动装箱返回的
    整数。您的代码显然不再引用它,因为
    value
    被设置为reference
    100
    。这似乎表明它有资格进行垃圾收集,但我不同意。
    整数
    类以符合。因此,当
    m
    退出时,缓存仍将包含对
    50
    中已装箱的
    整数的引用,从而使其不符合垃圾收集的条件


    我尝试使用此程序测试此行为:

    public class Currency {
        String name = new String();
        static Integer value = new Integer();
        static void getCurrency(Integer v) {
            Currency c = new Currency();
            c.value = v;
        }
        public static void m() {
            Currency.getCurrency(50);
            Currency.getCurrency(100);
        }
        public static void main(String[] argv) {
            Currency.m();
        }
    }
    
    表明,至少在本例中,未缓存的
    整数
    已被垃圾收集,而缓存的整数未被垃圾收集。这表明,即使没有明确引用
    50
    ,它仍然没有资格进行垃圾收集,因为缓存中存储了引用

    我承认这并不能证明什么,因为首先,
    System.gc()
    不能保证它将收集所有(或任何)可用内存。然而,我认为这应该表明问题并不像人们想象的那么简单,而且在最常见的JDK/JVM上,第六个值不符合垃圾收集的条件是合理的



    TL;DR-我不认为通过装箱
    50
    返回的
    Integer
    可以进行垃圾收集,因为它仍然被
    Integer
    类维护的缓存引用。

    getCurrency()
    的每次调用都将创建一个Currency对象。因此,对
    m()
    的调用将创建两个货币对象。但本例中传入的
    Integer
    值不应该是
    Integer
    缓存的一部分,因此不符合垃圾收集的条件吗?@Andreas抱歉,我在手机上回答了这个问题。@Vwin Yes。我不明白这会对我所说的有什么影响。我们都错了。没有对象符合GC条件,因为没有创建对象,因为
    new Integer()
    导致
    构造函数Integer()未定义
    编译错误,因此阻止代码运行。您能告诉我们您认为哪5个变量符合垃圾条件吗
    public class Test{
        public static final WeakReference<Integer> inCache = new WeakReference<>(50);
        public static final WeakReference<Integer> outOfCache = new WeakReference<>(10000);
        public static void main(String[] args){
            System.gc();
            System.out.println(inCache.get());
            System.out.println(outOfCache.get());
        }
    }
    
    50
    null