概述
String aa="aaa";
String cc=new String ("aaa");
的区别 ?
代码
public class T{
public static void main(String args[]){
String aa="aaa";
String cc=new String ("aaa");
}
}
1.通过java自带工具javap 得到运行使得指令集
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: ldc #16; //String aaa
2: astore_1
3: new #18; //class java/lang/String
6: dup
7: ldc #16; //String aaa
9: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/String;)V
12: astore_2
13: return
只看有关部分:
0: ldc #16; //String aaa
2: astore_1
String aa="aaa"; 对应
ldc: 从常量池(加载类时,将数字、字符、字符创常量导入方法区,
具体存储请看有关jvm内存模型 资料) 中得到字符串对 象("aaa"),压入栈中;
astore_1: 取栈中数据(赋值给aa)
String cc=new String ("aaa"); 对应
3: new #18; //class java/lang/String
6: dup
7: ldc #16; //String aaa
9: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/Stri
3: new #18; //class java/lang/String 创建对象
6: dup 复制栈顶压入栈
7: ldc #16; //String aaa
9: invokespecial #20; //Method java/lang/String."<init>":(Ljava/lang/Stri 调用构造方法
由此可知,aa 等内容就是常量池中字符串常量"aaa"的地址
cc 是以字符串常量"aaa"为参数新构造的字符串对象
由此 以下问题就显而易见了
String aa="aaa";
String bb="aaa";
String cc=new String("aaa");
System.out.println(aa==bb); true//aa,bb都是方法区中字符串常量那个对象,
一个地址 (aa==bb就相当于 aa==aa 或 bb==bb)
System.out.println(aa=cc); false //cc可以看成是以aa为参数,new的字符串
2.通过java 自带工具jmap(jdk1.6以后)查看此过程创建了几个对象
jmap -histo {pid}
num #instances #bytes class name
----------------------------------------------
11: 1951 46824 java.lang.String
若运行String aa="aaa"; 以后
num #instances #bytes class name
----------------------------------------------
11: 1952 46848 java.lang.String
可以看到 增加了1个 String 实例,对象就是 aa指向的字符串常量对象
若运行String cc=new String("aaa"); 以后
num #instances #bytes class name
----------------------------------------------
11: 1953 46872 java.lang.String
可以看到 增加了2个 String 实例,其中包括 常量池中字符串常量对象 ,还有 new的cc对象
若运行String aa="aaa"; String cc=new String("aaa"); 以后
num #instances #bytes class name
----------------------------------------------
11: 1953 46872 java.lang.String
虽然两个语句都运行,但只增加了2个对象,常量池中字符串常量对象,new的cc对象
(常量池中字符串常量创建一次,并且共享数据)
ldc指令格式:ldc,index
ldc指令过程:
要执行ldc指令,JVM首先查找index所指定的常量池入口,在index指向的常量池入口,
JVM将会查找CONSTANT_Integer_info,CONSTANT_Float_info和CONSTANT_String_info入口。
如果还没有这些入口,JVM会解析它们。而对于上面的hahaJVM会找到CONSTANT_String_info入口,
同时,将把指向被拘留String对象(由解析该入口的进程产生)的引用压入操作数栈。
3.做下面测试(使用javap,和jmap工具,jdk版本1.6)
public static void main(String args[]){
//10: 1935 46440 java.lang.String
String aa="aaa";
//10: 1936 46464 java.lang.String
String bb="aa"+"a"; //编译时在class文件中编译器只保留"aaa" 字符串常量,可以通过javap命令知道
//10: 1936 46464 java.lang.String
String dd="aaa";
//10: 1936 46464 java.lang.String
String ee="bbb";
//10: 1937 46488 java.lang.String
String cc=new String ("aaa");
//10: 1938 46512 java.lang.String
t();
}
public static void t(){
//10: 1938 46512 java.lang.String
String aa="aaa";
//10: 1938 46512 java.lang.String
String bb="aa"+"a";
//10: 1938 46512 java.lang.String
String dd="aaa";
//10: 1938 46512 java.lang.String
String ee="bbb";
//10: 1938 46512 java.lang.String
String cc=new String ("aaa");
//10: 1939 46536 java.lang.String
}
注: 测试 aa==bb==cc true
最后
以上就是活力外套为你收集整理的老生常谈-- String aa="aaa", String aa=new String("aaa");的全部内容,希望文章能够帮你解决老生常谈-- String aa="aaa", String aa=new String("aaa");所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复