1

我做了一个不可变的分数类(我想是的,一切都是最终的)。我读到字符串有这个“池”,一旦“asd”被实例化,所有其他对“asd”的引用都会指向第一个。(如果我理解正确的话)那么我将这个“池”重新创建为一个包含所有创建分数的超类是否有意义。可能有一个静态工厂方法在创建新分数之前首先检查现有分数池?
    var a = new Fraction(3,4);
    var b = a;
    var c = new Fraction(3,2);
    System.out.println(a + " " + b + " " + (a == b)); // 3/4 3/4 true

    b = a.add(b);

    System.out.println(a + " " + b + " " + (a == b)); // 3/4 3/2 false

    System.out.println(b + " " + c + " " + (b == c)); // 3/2 3/2 false (should be true but add() returns a new fraction)

这个想法是否值得做,即它会比平均实例化具有相同值的新分数更快吗?

4

1 回答 1

2

如果你持有所有创建的分数,那么你就有内存泄漏。(请注意,String池不包含所有创建的字符串,仅包含在源代码中以文字形式出现的字符串,以及您.intern()自己调用的任何字符串。)

缓存常用分数可能是有意义的,例如Fraction(n, 1)合理的整数范围和Fraction(n, m)较小的范围。但是您必须权衡不创建新对象的节省与每次检查对象是否已在缓存中的成本;净收益最多可能是微不足道的,并且在许多实际应用中可能是负面的,因此您需要使用一些合适的基准来测试它。

一种更简单的方法是提供一些预制常量,如、Fraction.ZEROFraction.ONE等。然后,您的 API 的用户可以引用这些常量,而不是在每次需要使用这些常用分数时都使用文字值构造新实例。这是标准库类所采用的方法:没有内置池或缓存,但您可以编写,或代替实例化这些常用数字的多个副本。Fraction.ONE_HALFFraction.ONE_THIRDBigIntegerBigInteger.ZEROBigInteger.ONEBigInteger.TEN

于 2021-03-17T23:13:58.957 回答