new & valueof & 直接赋值的区别
首先来看下面这段代码
public static void main(String[] args) {
String s1 = "s1";
String s2 = new String("s2");
String s3 = String.valueOf(12345);
}
编译成class文件之后,使用eclipse class file viewer查看
// Method descriptor #15 ([Ljava/lang/String;)V
// Stack: 3, Locals: 4
public static void main(java.lang.String[] args);
0 ldc <String "s1"> [16]
2 astore_1 [s1]
3 new java.lang.String [18]
6 dup
7 ldc <String "s2"> [20]
9 invokespecial java.lang.String(java.lang.String) [22]
12 astore_2 [s2]
13 sipush 12345
16 invokestatic java.lang.String.valueOf(int) : java.lang.String [25]
19 astore_3 [s3]
20 return
Line numbers:
[pc: 0, line: 12]
[pc: 3, line: 13]
[pc: 13, line: 14]
[pc: 20, line: 20]
Local variable table:
[pc: 0, pc: 21] local: args index: 0 type: java.lang.String[]
[pc: 3, pc: 21] local: s1 index: 1 type: java.lang.String
[pc: 13, pc: 21] local: s2 index: 2 type: java.lang.String
[pc: 20, pc: 21] local: s3 index: 3 type: java.lang.String
}
对于第一行代码 String s1 = "s1"; 编译成字节码之后,对应两条指令,
-
ldc指令从运行时常量池push一个值到Frame的操作数栈上面,这个值在这里就是"s1"字符串的引用,
-
astore指令将objectref存储到局部变量,这里也就是存储到局部变量s1。
对于第二行代码 String s2 = new String("s2");编译成字节码之后,对于的指令也用高亮标注出来了,这里把操作数栈的情况画了出来,希望能帮助理解。橙色标注的为栈顶元素。
-
new指令会在堆上创建对象,操作数栈里压入创建的objectref,
-
-
ldc指令依然是从常量池push一个值到Frame的操作数栈上,这个值是"s2"字符串的引用。
|
"s2"_ref |
objectref |
objectref |
... |
-
invokespecial 指令调用一个方法,这里就是调用String的构造函数,调用完成之后栈上还有一个objectref
-
astore指令将objectref存储到局部变量,这里也就是存储到局部变量s2。
对于第三行代码 String s3 = String.valueOf(12345); 编译成字节码之后对应的指令,
-
sipush 将 12345 压栈
-
invokestatic 调用 String.valueof(int) 方法
-
astore 将栈顶的对象引用存储到本地变量s3 (这里不再深究这个栈顶元素是怎么来的了)
PMD检查代码的时候,有这样的warning: Avoid instantiating String objects.Call String.valueOf() instead. PMD给出的原因是In JDK 1.5, calling new String() causes memory allocation. String.valueOf() is more memory friendly.
经过上面的分解,我们应该知道原因了,以后写代码的时候,初始化一个字符串, String s1 = "s1"; 这样的代码肯定比 String s2 = new String("s2");代码强,将其他类型的值转换成String的时候,valueof方法比new方法效率也高。
备注:
A frame is used to store data and partial results(局部变量,操作数栈), as well as to perform dynamic linking , return values for methods, and dispatch exceptions.
ldc指令的操作数栈: ...->...,value (value是int,float 或者 string 类型的引用)
astore的操作数栈: ...,objectref->...
new指令的操作数栈: ...->...,objectref
dup指令的操作数栈: ...,value->...,value,value
invokespecial的操作数栈: ...,objectref, [agr1,[arg2...]]->...
invloestatic的操作数栈:..., [arg1, [arg2...]] -> ...
如果要理解的更透彻建议阅读以下参考资料:
posted on 2008-07-28 14:27
jht 阅读(1697)
评论(1) 编辑 收藏 所属分类:
J2SE