(转)Java字符串
转自:http://blog.sina.com.cn/s/blog_899678b90101brz0.html
创建字符串有两种方式:两种内存区域(字符串池,堆)
1," " 引号创建的字符串在字符串池中
2,new,new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则导致浪费池的空间)
另外,对字符串进行赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用;如String str2=str1+ "abc";
比较两个已经存在于字符串池中字符串对象可以用"=="进行,拥有比equals操作符更快的速度。
java 字符串池
java运行环境有一个字符串池。比如String str="abc"时,会首先查看字符串池中是否存在字符串"abc",如果存在则直接将"abc"赋给str,如果不存在则会先在字符串池中新建一个字符串"abc",然后再将其赋给str。如果执行代码
- String str1="abc";
- String str2="abc";
- System.out.println(str1==str2);
则这段代码结果就会是true。执行str1时,会首先检查字符串池中是否存在"abc",如果有则直接赋给str1,如果没有则在字符串池中创建一个"abc"然后再赋给str1,当执行到str2时,检查字符串池已经存在了"abc",因此直接赋给str2,str1与str2指向同一个对象,所以结果为true。
而执行String str=new String("abc")时,不管字符串池中有没有"abc"都会在堆中新建一个字符串对象然后将其赋给str引用。所以执行如下代码
- String str1=new String("abc");
- String str2=new String("abc");
- System.out.println(str1==str2);
结果就会为false,因为str1与str2指向的分别是两个不同的对象。
- String str1="abc";
- String str2="def";
- String str3=str1+str2;
- System.out.println(str3=="abcdef");
- //结果肯定是为false
因为str3指向堆中的"abcdef"对象,而"abcdef"是字符串池中的对象,因为结果为false。JVM对String str="abc"对象放在常量池中是在编译时做的,而String str3=str1+str2是在运行时刻才能知道的。new对象也是在运行时才做的。而这段代码总共创建了5个对象,字符串池中两个、堆中三个。+运算符会在堆中建立来两个String对象,也就是说从字符串池中复制这两个值,然后在堆中创建两个对象,然后再建立对象str3,然后将"abcdef"的堆地址赋给str3。
而如果
- String str="abc"+"def"; //直接将"abcdef"放入字符串池中
- System.out.println(str=="abcdef");
- //结果为true
- String str1="abc";
- String str2=str1+"def"; //str1是在堆中创建的对象
- System.out.println(str2=="abcdef");
- //结果为false
由于字符串对象的大量使用(它是一个对象,一般而言对象总是在堆中分配内存),Java中为了节省内存空间和运行时间(如比较字符串时,==比equals()快),在编译阶段就把所有的字符串文字放到一个字符串池中,而运行时字符串池成为常量池的一部分。字符串池的好处,就是该池中所有相同的字符串常量被合并,只占用一个空间。
我们知道,对两个引用变量,使用==判断它们的值(引用)是否相等,即指向同一个对象:
String s1 = "abc" ;
String s2 = "abc" ;
if( s1 == s2 ) System.out.println("s1,s2 refer to the same object");
else System.out.println("trouble");
这里的输出显示,两个字符串文字保存为一个对象。就是说,上面的代码只在字符串中创建了一个String对象。
现在看String s = new String("abc");语句,这里"abc"本身就是pool中的一个对象,而在运行时执行new String()时,将字符串池中的对象复制一份放到堆中,并且把堆中的这个对象的引用交给s持有。ok,这条语句就创建了2个String对象。
String s1 = new String("abc") ;
String s2 = new String("abc") ;
if( s1 == s2 ){ //不会执行的语句}
这时用==判断就可知,虽然两个对象的"内容"相同(equals()判断),但两个引用变量所持有的引用不同,上面的代码创建了几个String 对象? (3个,字符串池中1个,堆中2个。)
再看如下示例:
String str = new String("abc"); // 语句(1)
String str1 = "abc";// 语句(2)
String str2 = new String("abc");// 语句(3)
System.out.println(str == str1);// 语句(4) false
System.out.println(str == str2);// 语句(5) false
System.out.println(str1 == str2);// 语句(6) false
System.out.println(str == str.intern());// 语句(7) false
System.out.println(str1 == str1.intern());// 语句(8) true
System.out.println(str.intern() == str2.intern());// 语句(9) true
String hello = "hello";// 语句(10)
String hel = "hel";// 语句(11)
String lo = "lo";// 语句(12)
System.out.println(hello == "hel" + "lo");// 语句(13) true
System.out.println(hello == "hel" + lo);// 语句(14) fasle
(转)Java字符串的更多相关文章
- Java 字符串格式化详解
Java 字符串格式化详解 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 文中如有纰漏,欢迎大家留言指出. 在 Java 的 String 类中,可以使用 format() 方法 ...
- Java字符串split函数的注意事项
Java字符串的split方法可以分割字符串,但和其他语言不太一样,split方法的参数不是单个字符,而是正则表达式,如果输入了竖线(|)这样的字符作为分割字符串,会出现意想不到的结果, 如, Str ...
- 关于java字符串编译优化问题
情景一:不好的字符串拼接习惯 起因是这样的:一个大牛在写了一篇关于java字符串优化问题的讲解,他提到:不要使用strObj+otherValue的方法将otherValue转换为字符串形式,因 ...
- Java字符串排列算法
Java字符串排列算法 题目:现有ABCDE 5个球 构成的排列组合 可重复抽取 最多取到16个 共有多少种组合方式? 比如:取1个球可以构成的组合有 A B C D E 共5种,取2个球可以构成的组 ...
- Java字符串转换
public class StringConvertToInt{ public static void main(String[] args) { String a ="12a34bW()5 ...
- Java字符串null相加
Java字符串null相加 最近和同事讨论了下面的一段代码: String a = null; a += a; System.out.println(a); 运行结果: nullnull 本着学习的态 ...
- JAVA字符串格式化String.format()的使用
JAVA字符串格式化-String.format()的使用常规类型的格式化 String类的format()方法用于创建格式化的字符串以及连接多个字符串对象.熟悉C语言的同学应该记得C语言的sprin ...
- Java字符串的10大热点问题,你都懂吗?
转自 威哥干JAVA http://www.codingke.com 下面我为大家总结了10条Java开发者经常会提的关于Java字符串的问题,如果你也是Java初学者,仔细看看吧: 1.如何比较字符 ...
- java 字符串为空问题
java 字符串为空问题 String testStr = null; System.out.println(testStr); if (testStr == null) { System.out.p ...
随机推荐
- mysql union和union all的区别
union 对两个结果集进行并集操作,重复数据只显示一次 Union All,对两个结果集进行并集操作,重复数据全部显示 工具/原料 mysql 数据库 方法/步骤 student表数据 使用 ...
- jQuery鼠标悬停内容动画切换效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- bzoj1051
就是一个tarjan #include<iostream> #include<stack> #include<cstdio> using namespace std ...
- js-新窗口打开页面
window.open(basePath+"/web/homeIndex?code="+code); 1.超链接<a href="http://www.xxx.ne ...
- HTMLTestRunner修改Python3的版本
在拜读虫师大神的Selenium2+Python2.7时,发现生成HTMLTestRunner的测试报告使用的HTMLTestRunner的模块是用的Python2的语法.而我本人比较习惯与Pytho ...
- CSS实现兼容性的渐变背景(gradient)效果
利用css 3实现渐变可以很方便的更改它的颜色,并且能够减少图片的制作,但是它的兼容性并不好,下面的代码就是实现利用css 渐变兼容的代码: .gradient{ width:300px; heigh ...
- 在编译向该请求提供服务所需资源的过程中出现错误。请检查下列特定错误详细信息并适当地修改源代码。 编译器错误消息: CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\41c191fd\ff9345c5\App_Web_login.cshtml.65793277
本地开发环境没问题,但是发布到服务器出现问题或则直接在IIS上修改东西就给我抛出以下错误: 未能写入输出文件"c:\Windows\Microsoft.NET\Framework64 \v4 ...
- iOS随机生成数字
有时候我们需要在程序中生成随机数,但是在Objective-c中并没有提供相应的函数,好在C中提供了rand().srand().random().arc4random()几个函数.那么怎么使用呢?下 ...
- css选择器([class*=" icon-"], [class^=icon-] 的区别)
官方解释: [attribute^=value],a[src^="https"],选择其 src 属性值以 "https" 开头的每个 <a> 元素 ...
- Gulp解决发布线上文件(CSS和JS)缓存问题
Gulp解决发布线上文件(CSS和JS)缓存问题 本文的缘由:目前经常线上发布文件后要不断的刷新页面及过很长时间,页面上的CSS和JS文件才能生效,特别对于目前做微信商城的时候,微信内置的浏览器缓存非 ...