【问题标题】:Are all immutable objects re-usable?所有不可变对象都可以重用吗?
【发布时间】:2013-09-23 03:47:43
【问题描述】:

从一本有效的 Java 书籍中可以看出,“如果一个对象是不可变的,则它总是可以被重用”。

String s = "shane";
String p = "shane";

这个版本使用single String instance,而不是创建一个新的 每次执行时。此外,可以保证该对象将 由在同一虚拟机中运行的任何其他代码重用,该虚拟机恰好包含 相同的字符串文字。

下面的 final 类也是不可变的呢?点对象可以重复使用吗?

public final class Point {
  private final int x, y;

  public Point(int x, int y) {
   this.x = x;
   this.y = y;
  }

  public int getX() { return x; }
  public int getY() { return y;
 }

谁能给我一个上面immutable class的例子,它的对象/实例可以被重用吗?我只是对可重用性如何发生感到困惑?

我能够与String 和Integer 类相关联,但不能与用户定义的类相关。

【问题讨论】:

  • Immutable class == immutable Object
  • 它可以被重复使用,但这只是对字符串类的保证。

标签: java oop immutability value-objects


【解决方案1】:

它“可以”重复使用,因为您可以在多个地方使用同一个对象,这很好。但它不会是,自动的。 JVM 本身管理 -128 - 127 范围内的 Integer 对象的重用

Integers caching in Java

“实习”字符串(包括文字)同样由 JVM 管理。最接近自动重用的方法是将构造函数设为私有,并创建一个工厂方法:

 Point.create(int x, int y)

并让实现维护您想要重用的对象缓存(例如整数有效缓存 -128 到 127),但您必须自己完成这项工作。

编辑:

你基本上有:

 private static final Map<Pair<Integer, Integer>, Point> cache = new HashMap<>();

 public Point create(int x, int y) {
   Pair<Integer, Integer> key = Pair.of(x, y);
   if (cache.containsKey(key)) {
     return cache.get(key);
   }
   Point p = new Point(x, y);
   cache.put(key, p);
   return p;
 }

编辑: 或者,将 hashCode() 和 equals() 添加到 Point 类,然后只使用 HashSet。会更简单。

【讨论】:

  • 怎么可能,即使我使用静态工厂方法...我仍然在每次调用 Point.create(int x, int y) 时创建一个新的 Point()...您可以在帖子中添加更多内容以使其更清晰吗?
  • @Shane 添加了带有示例的编辑。您并不总是创建一个新的 Point() - 工厂方法的要点是您可以创建一个新点,或者如果它是重复的,则返回以前创建的点。
  • +1。 JVM中不可变对象的小规模缓存的其他示例包括BigDecimal.ZERO/ONE/TEN、Collections.EMPTY_LIST/EMPTY_SET/EMPTY_MAP和Boolean.TRUE/FALSE。共同的因素是没有尝试缓存所有值,也没有强制缓存,只是为了方便共享一些可能被多次使用的值在一个程序中。
  • 严格来说,您应该使用 ConcurrentHashMap 或其他线程安全的东西。顺便说一句,这段代码是可以的,但是在愤怒中使用它会在以后造成麻烦。
【解决方案2】:

可重用仅仅意味着改变“参考”变量的值。 例如一个 int 可以被重用并且它的值改变了 数据类型有点不同,例如使用“新”实例重新启动引用变量,例如我的框架=新的 JFrame() 声明为“final”的变量是“常量”并且是可变的。

上面的类本身要求它的引用变量在初始化时被声明为“final”是可变的,尽管它的内容实际上是可变的,困难在于定义上下文的哪个(变量或类定义)部分是可变的。

【讨论】:

    【解决方案3】:

    不变性意味着当一个对象被创建时,它在创建时的状态将在其生命周期内保持不变。是的,您展示的类和该类的对象是不可变的,因为您在构造函数中初始化状态并且没有设置器。

    关于重用:是的,您可以在需要 Point 类型的对象的地方一遍又一遍地重用同一个对象,但为此目的,您必须在为此创建对象后保留它。作为@詹姆斯 建议,您可以使用工厂来创建对象,当您请求 Point 对象时,该工厂可以决定是需要创建新对象还是使用现有对象。

    【讨论】:

      猜你喜欢
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      • 2011-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多