JAVA中创建字符串的两种方式的区别
2015-08-20 00:26
561 查看
我们知道,通常在Java中创建一个字符串会有两种方式,通过双引号直接赋值和通过构造器来创建。
String x = abcd;
String y = new String(abcd);
然而,这两种方式之间的区别是什么?分别应用于哪些情况,之前还不是很懂。
1、双引号的方式
String x = abcd;
String y = abcd;
System.out.println(x==y);//true
System.out.println(x.equals(y));//true
上面的输出结果:
x==y 的结果为true 是因为通过双引号赋值的方式之后,x 和 y 都是指向同一个内存地址,他们的引用都是指向方法区中的同一个内容,引用地址是一样的, 当同一个String字面值无论被创建多少次,始终只有一个内存地址被分配,之后的都是这个String的拷贝,Java中称作“字符串驻留”,所有的字符串常量在编译之后都会自动的驻留。x = abcd这种方式创建的时候首先会查看字符串池中是否已经存在,存在就直接返回PermGen中的该String对象,否则就会创建一个新的String对象,之后再放进字符串池中。
JVM里,考虑到垃圾回收(Garbage Collection)的方便,将 heap 划分为三部分: young generation (新生代)、 tenured generation(old generation)(旧生代)和 permanent generation( permgen )(永久代)
字符串池是为了解决字符串重复的问题,生命周期长,它存在于 permgen 中。
编译 Java 源代码时,源文件中出现的双引号内的字符串都被收纳到常量池中,用 CONSTANT_utf8_info 项存储着。
JVM 中,相应的类被加载运行后,常量池对应的映射到 JVM 的运行时常量池中。其中每项 CONSTANT_utf8_info(也就试记录那些字符串的)都会在常量引用解析时,自动生成相应的 internal String,记录在字符串池中。
2、构造器的方式
String a = new String(abcd);
String b = new String(abcd);
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
上面代码运行结果:
a==b 为false 是因为通过new 构造器的方法创建之后,在heap堆中分别分配了两个内存地址。a 和 b 分别指向了堆中的两个不同的对象,不同的对象就会有不同的地址分配。
下面这张图就很好的阐述了上面的两种情况:
constructor
字符串驻留的操作在运行时刻仍然会存在,即使是通过构造器的方式创建的。
String c = new String(abcd).intern();
String d = new String(abcd).intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
应用的情况:
建议在平时的应用中,应尽量使用String x = abcd这种方式来创建字符串,而不是String x = new String(abcd); 因为用new构造器的方式肯定会开辟一个新的heap堆空间,而双引号的方式则是采用了String interning(字符串驻留)方式进行了优化,效率会比构造器的方式高。
如果出于某种原因,你确实需要再heap堆中创建一个新的String对象,那么就可以使用构造器的方式来解决。
当然,以上的这些都只是我自己的理解,因为也是个新手,接触Java的时间也还不长,肯定也有很多东西理解有误,关于那个字符串驻留的问题解释的不是很透彻,只是知道一些浅显的大概意思,希望大牛们批评指正,感谢!
转载地址:http://www.2cto.com/kf/201412/362343.html
String x = abcd;
String y = new String(abcd);
然而,这两种方式之间的区别是什么?分别应用于哪些情况,之前还不是很懂。
1、双引号的方式
String x = abcd;
String y = abcd;
System.out.println(x==y);//true
System.out.println(x.equals(y));//true
上面的输出结果:
x==y 的结果为true 是因为通过双引号赋值的方式之后,x 和 y 都是指向同一个内存地址,他们的引用都是指向方法区中的同一个内容,引用地址是一样的, 当同一个String字面值无论被创建多少次,始终只有一个内存地址被分配,之后的都是这个String的拷贝,Java中称作“字符串驻留”,所有的字符串常量在编译之后都会自动的驻留。x = abcd这种方式创建的时候首先会查看字符串池中是否已经存在,存在就直接返回PermGen中的该String对象,否则就会创建一个新的String对象,之后再放进字符串池中。
JVM里,考虑到垃圾回收(Garbage Collection)的方便,将 heap 划分为三部分: young generation (新生代)、 tenured generation(old generation)(旧生代)和 permanent generation( permgen )(永久代)
字符串池是为了解决字符串重复的问题,生命周期长,它存在于 permgen 中。
编译 Java 源代码时,源文件中出现的双引号内的字符串都被收纳到常量池中,用 CONSTANT_utf8_info 项存储着。
JVM 中,相应的类被加载运行后,常量池对应的映射到 JVM 的运行时常量池中。其中每项 CONSTANT_utf8_info(也就试记录那些字符串的)都会在常量引用解析时,自动生成相应的 internal String,记录在字符串池中。
2、构造器的方式
String a = new String(abcd);
String b = new String(abcd);
System.out.println(a==b);//false
System.out.println(a.equals(b));//true
上面代码运行结果:
a==b 为false 是因为通过new 构造器的方法创建之后,在heap堆中分别分配了两个内存地址。a 和 b 分别指向了堆中的两个不同的对象,不同的对象就会有不同的地址分配。
下面这张图就很好的阐述了上面的两种情况:
constructor
字符串驻留的操作在运行时刻仍然会存在,即使是通过构造器的方式创建的。
String c = new String(abcd).intern();
String d = new String(abcd).intern();
System.out.println(c == d); // Now true
System.out.println(c.equals(d)); // True
应用的情况:
建议在平时的应用中,应尽量使用String x = abcd这种方式来创建字符串,而不是String x = new String(abcd); 因为用new构造器的方式肯定会开辟一个新的heap堆空间,而双引号的方式则是采用了String interning(字符串驻留)方式进行了优化,效率会比构造器的方式高。
如果出于某种原因,你确实需要再heap堆中创建一个新的String对象,那么就可以使用构造器的方式来解决。
当然,以上的这些都只是我自己的理解,因为也是个新手,接触Java的时间也还不长,肯定也有很多东西理解有误,关于那个字符串驻留的问题解释的不是很透彻,只是知道一些浅显的大概意思,希望大牛们批评指正,感谢!
转载地址:http://www.2cto.com/kf/201412/362343.html
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统