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 阅读(1715) 
评论(1)  编辑  收藏  所属分类: 
J2SE