受到this question上的评论的启发,我很确定Java String
是在运行时而不是编译时间实现的 - 当然,事实上可以在不同的时间编译类,但是仍然会在运行时指向相同的引用。
我似乎无法找到任何证据支持这一点。有人可以证明这一点吗?
答案 0 :(得分:17)
优化在两个地方都会发生(或至少可能发生):
String
对象,但这是一个明显的优化。这实际上不是实习生 - 只是不断优化。(我有一个模糊的回忆,Java 7围绕“小jar文件”的一部分工作包括整个jar文件的单个字符串池......但我可能是非常错误的。)
编辑:JVM规范的第5.1节,"The Runtime Constant Pool"详细说明了这一点:
要派生字符串文字,Java 虚拟机检查序列 由...给出的字符 CONSTANT_String_info结构。
如果String.intern方法有 以前在一个实例上调用过 包含序列的String类 与...相同的Unicode字符 由CONSTANT_String_info给出的 结构,然后是字符串的结果 字面派生是一个参考 类String的相同实例。
否则,是一个新的类实例 创建包含的字符串 给出的Unicode字符序列 通过CONSTANT_String_info结构; 该类实例是结果 字符串文字推导。最后, 新String的实习方法 调用了实例。
答案 1 :(得分:0)
运行系统。
JLS和JVM规范将javac编译指定为类文件,这些类文件包含常量声明(在常量池中)和代码中的常量用法(javac可以作为基元/对象引用值内联)。对于编译时字符串常量,编译器生成用于构造String实例的代码并为它们调用String.intern(),以便JVM自动实现字符串常量。这是来自JLS的行为要求:
http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28
类型为String的编译时常量表达式总是“实例化”,以便使用String.intern方法共享唯一的实例。
但是这些规范既没有概念,也没有任何特定String intern池结构/引用/句柄的定义,无论是编译时还是运行时。 (当然,一般来说,JVM规范并没有要求对象的任何特定内部结构:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7)
没有提到实习池结构的原因是因为它们完全使用String类处理。实习池是String类的私有静态/类级结构(未由JLS和JVM规范& javadoc指定)。
在运行时调用String.intern()时,会将对象添加到实习池中。实体池由String类私有使用 - 当代码创建新的String实例并调用String.intern()时,String类确定是否重用现有的内部数据。优化可以由JIT编译器在运行时执行。
这里没有编译时贡献,禁止内联常量值。