final String vs final Integer

时间:2012-11-17 14:15:42

标签: java

我的java类

private static final String constantString = "Constant";    
private static final Integer constantInteger = 5;
public static void main(String[] args) {
    String s2 = constantString + "append"; // LINENUMBER 9
    Integer i2 = constantInteger + 7; // LINENUMBER 10
}

字节代码

 LINENUMBER 9 L0
    LDC "Constantappend"
    ASTORE 1
   L1
    LINENUMBER 10 L1
    GETSTATIC TestClass.constantInteger : Ljava/lang/Integer;
    INVOKEVIRTUAL java/lang/Integer.intValue()I
    BIPUSH 7
    IADD

问题1:为什么编译器没有用5替换最终的Integer(constantInteger)值,但是对于String,它确实没有!

如果删除整数变量的最终关键字

java代码:

private static Integer constantInteger = 5;

字节代码:

LINENUMBER 10 L1
GETSTATIC TestClass.constantInteger : Ljava/lang/Integer;
INVOKEVIRTUAL java/lang/Integer.intValue()I
BIPUSH 7

两种不同情况下的字节代码相同(静态最终整数,静态整数)

问题2:那么使Integer最终有什么用?

4 个答案:

答案 0 :(得分:6)

推测:原因是字符串实习。编译器实例化字符串并具有连接字符串连接的优化。但它没有实习数字,显然缺乏优化。

我想不出有什么理由不能优化整数情况,除了它还没有在编译器中实现。正如其他答案中所提到的,Integer +涉及装箱/拆箱操作,与字符串+及其隐式StringBuilder优化和实际逻辑完全不同。因此,如果查看,String +优化可能从编译器实现点“免费”出现。

答案 1 :(得分:5)

编译器不会注意到具有非null值的最终Integer必然是非null。所以它继续并将其拆箱。 JIT编译器完全有可能在加工机器代码的过程中改进这一点;对于应用程序的性能来说,这似乎是不太可能的。

'最终'是关于语义,而不是表现。语言保证了语义;性能完全是实现者的心血来潮。所以,回答问题#2'显式:最后一点是具有防止修改的语义。还要注意嵌入式匿名类的规则,它们只能使用最终的局部变量。

答案 2 :(得分:3)

答案简短:尝试static final int constantInteger = 5

编译器只能替换常量表达式。 Java具有所谓的原始值,即以小写字符(long,int,char,...)开头的类型。这些值不是对象,因此它们不能具有状态并且可以直接替换。

作为优化字符串对象也可以被编译器视为常量。在运行时,String只是一个容纳字符数组的容器,但在编译时,编译器假装String只是字符数据。但是,String是唯一一个针对此例外的类。

出于类似的原因,您可以使用StringClass,但注释中的值没有其他对象类型。

答案 3 :(得分:1)

来自Java Language Specification, v3

  

由常量表达式计算的字符串(第15.28节)计算在   编译时间,然后将其视为文字。

您的字符串表达式由两个文字组成,在编译时计算为单个文字。整数没有这样的待遇。