Java 在 for-each 循环中实习字符串

Does Java intern Strings in a for-each loop

我读过有关 SO 的问题,解释说 Java 会自动实习字符串文字,并且显然会在调用 intern() 时实习。但是,我想知道是否在一个循环中(在我的例子中是 foreach 循环)字符串是否也被自动保留。我问是因为我正在实习字符串以在几个非常大的 LinkedHashMaps 中节省内存,并且想知道调用 intern() 是否多余。

示例:

String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
  map.put(s, 1f);
}

下一个示例在内存使用方面是否会与第一个(假设相同 array 值)有任何差异,或者 s 是否已经在该点实习?

String array[] = createLargeArbitraryArray();
Map<String, Float> map = new LinkedHashMap<String, Float>(array.length);
for (String s : array)
  map.put(s.intern(), 1f);
}

我意识到在这种情况下,可能没有等效的字符串,但在我的情况下,我有几个映射的自定义键,这些映射最终确实使用了重复的字符串值,我想知道是否调用 intern() 在这一点上节省内存是多余的还是多余的。

要补充这个问题,如果数组是从文字创建的(在这种情况下,它们最初是驻留的),然后作为参数传递给方法,上面的循环是否会使用驻留字符串?即:

/**
 * @param array created from literals
 */
public void populateMap(String[] array) {
  for (String s : array)
    map.put(s, 1f); // Interned or not?
}

在这种情况下,要么 s 被驻留,因为 array 一开始就被驻留,要么 s 没有被驻留,因为它在循环参数中被声明为新对象.哪个是正确的?

编辑:为了进一步解释我实习的原因,我想释放堆中的内存以避免达到最大堆大小或 GC 开销限制。在这种情况下,性能和速度对我来说并不是极其重要。

在这里明确调用 intern() 是正确的方法(或者像 PC luddite 所说的,检查你是否真的需要 interning)。我不知道 JVM 中有任何 JIT 编译器可以做到这一点(即使有一些优化可以做到这一点,您也不应该依赖它)。

如果数组是从驻留字符串创建的,然后传递给方法然后使用,那么将使用 "interned" 字符串。不会创建额外的字符串。