2

我正在阅读函数式 Java 库的源代码并注意到这一点:

public static <T> Option<T> none() {
    return new None<T>();
}

我想知道为什么他们不总是返回一个单例参数,特别是因为 None 的相等实现:

private static final class None<A> extends Option<A> { 

...

@Override
public int hashCode() {
    return 31;
}

@Override
public boolean equals(Object obj) {
   if (this == obj)
      return true;
   if (obj == null)
      return false;
   if (getClass() != obj.getClass())
      return false;
   return true;
}

}

所以我在 Functional Java 的论坛上进行了搜索,我发现了这个问题和答案:

是否可以将其设置为不会为每次调用 none 创建一个新的 None ,我们可以在所有情况下使用单个对象来表示 None 吗?

不,但是,谁在乎呢?如今,JIT 优化器可以很好地处理这些事情。

我的问题是 JIT 优化器如何以不需要返回单例的方式处理这个问题。我知道对象创建很便宜,但我认为单例会更便宜,在这种情况下它不会增加任何复杂性。

4

2 回答 2

3

不,我知道的 Java VM 不执行此类优化。使用现代 JVM,创建新对象实际上比寻找现有对象更便宜。他们在这个常见问题解答中的意思是短暂的、被丢弃的对象并不会真正影响垃圾收集时间(但可能会增加 GC 频率)。我也可以想象 JVM 执行逃逸分析并将此类对象分配到堆栈上而不是堆上。

不过我觉得挺浪费的。查看java.lang.Integer(和所有其他原始包装器)缓存或Optional.absent()Guava

public static <T> Optional<T> absent() {
  return (Optional<T>) Absent.INSTANCE;
}

在 JDK 中还有很多类似的优化:enums 是单例,Collections.emptyList()总是返回相同的实例,等等。

于 2013-02-05T19:37:04.523 回答
1

它更安全,否则我们需要依赖擦除。

创建一个对象可能仍然比查找一个缓存的对象更昂贵。参见 java8 的可选:

http://hg.openjdk.java.net/lambda/lambda/jdk/file/ad394630273b/src/share/classes/java/util/Optional.java

   43     private final static Optional<?> EMPTY = new Optional<>();

   63      * There is no guarantee that it is a singleton.

   69     @SuppressWarnings("unchecked")
   70     public static<T> Optional<T> empty() {
   71         return (Optional<T>) EMPTY;
   72     }
于 2013-02-05T20:59:04.007 回答