java 字符串池

java运行环境有一个字符串池。比如String str="abc"时,会首先查看字符串池中是否存在字符串"abc",如果存在则直接将"abc"赋给str,如果不存在则会先在字符串池中新建一个字符串"abc",然后再将其赋给str。如果执行代码

Java代码  
  1. String str1="abc";
  2. String str2="abc";
  3. System.out.println(str1==str2);
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引用。所以执行如下代码

Java代码  
  1. String str1=new String("abc");
  2. String str2=new String("abc");
  3. System.out.println(str1==str2);
String str1=new String("abc"); String str2=new String("abc"); System.out.println(str1==str2);

结果就会为false,因为str1与str2指向的分别是两个不同的对象。

Java代码  
  1. String str1="abc";
  2. String str2="def";
  3. String str3=str1+str2;
  4. System.out.println(str3=="abcdef");
  5. //结果肯定是为false
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。

而如果

Java代码  
  1. String str="abc"+"def";   //直接将"abcdef"放入字符串池中
  2. System.out.println(str=="abcdef");
  3. //结果为true
  4. String str1="abc";
  5. String str2=str1+"def";    //str1是在堆中创建的对象
  6. System.out.println(str2=="abcdef");
  7. //结果为false
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个。)

创建字符串有两种方式:两种内存区域(字符串池,堆)
1," " 引号创建的字符串在字符串池中
2,new,new创建字符串时首先查看池中是否有相同值的字符串,如果有,则拷贝一份到堆中,然后返回堆中的地址;如果池中没有,则在堆中创建一份,然后返回堆中的地址(注意,此时不需要从堆中复制到池中,否则导致浪费池的空间)
另外,对字符串进行赋值时,如果右操作数含有一个或一个以上的字符串引用时,则在堆中再建立一个字符串对象,返回引用;如String str2=str1+ "abc";  比较两个已经存在于字符串池中字符串对象可以用"=="进行,拥有比equals操作符更快的速度

java 字符串池【转】的更多相关文章

  1. java字符串池和字符串堆内存分配

    1. String str=new String("abc")和String str="abc"的字符串“abc”都是存放在堆中,而不是存在 栈中. 2. 其实 ...

  2. Java字符串池(String Pool)深度解析

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在工作中,String类是我们使用频率非常高的一种对象类型.JVM为了提升性能和减少内存开销,避免字符串的重复创建,其维护了一块特殊的内存 ...

  3. Java字符串池

    1. String类的两个构造方法 private final char value[]; private int hash; public String() { this.value = " ...

  4. Java字符串池(String Pool)深度解析(转)

    出自  http://www.cnblogs.com/fangfuhai/p/5500065.html 在工作中,String类是我们使用频率非常高的一种对象类型.JVM为了提升性能和减少内存开销,避 ...

  5. (转)Java字符串

    转自:http://blog.sina.com.cn/s/blog_899678b90101brz0.html 创建字符串有两种方式:两种内存区域(字符串池,堆)1," " 引号创 ...

  6. 161207、高并发:java.util.concurrent.Semaphore实现字符串池及其常用方法介绍

    实现字符串池: StrPool.java import java.util.ArrayList; import java.util.List; import java.util.concurrent. ...

  7. Java常量池解析与字符串intern简介

    在Java应用程序运行时,Java虚拟机会保存一份内部的运行时常量池,它区别于class文件的常量池,是class文件常量池映射到虚拟机中的数据结构. 关于class文件常量池的部分可以参考之前的博文 ...

  8. Java字符串常量池是什么?为什么要有这种常量池?

    简单介绍 Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池.我们知道String是java中比较特殊的类,我们可以使用new运算符创建String对象,也可以用双引 ...

  9. 理解Java字符串常量池与intern()方法

    String s1 = "Hello"; String s2 = "Hello"; String s3 = "Hel" + "lo ...

随机推荐

  1. 【shell脚本练习】grep sed awk

    下面是简单学习之后做得练习题,如果有不对的或者说解题思路不好的,请交流啊. Grep 练习 文件名grepfile Steve Blenheim:238-923-7366:95 Latham Lane ...

  2. ECMAScript 6 入门简介

    ECMAScript 6.0(以下简称ES6)是JavaScript语言的下一代标准,已经在2015年6月正式发布了.它的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级 ...

  3. JAVA之旅(一)——基本常识,JAVA概念,开发工具,关键字/标识符,变量/常量,进制/进制转换,运算符,三元运算

    JAVA之旅(一)--基本常识,JAVA概念,开发工具,关键字/标识符,变量/常量,进制/进制转换,运算符,三元运算 Android老鸟重新学一遍JAVA是什么感觉?枯燥啊,乏味啊,而且归纳写博客,都 ...

  4. E-JSON数据传输标准

    简介 E-JSON的设计目标是使业务系统向浏览器端传递的JSON数据保持一致,容易被理解和处理,并兼顾传输的数据量.E-JSON依托于http协议(rfc2616)与JSON数据交换格式(rfc462 ...

  5. XBMC源代码分析 1:整体结构以及编译方法

    XBMC(全称是XBOX Media Center)是一个开源的媒体中心软件.XBMC最初为Xbox而开发,可以运行在Linux.OSX.Windows.Android4.0系统.我自己下载了一个然后 ...

  6. Ubuntu 14 安装WPS

    在32位Ubuntu 14.04 安装 WPS,WPS For Linux版除延续Windows版相同体验外,更加尊重Linux用户特定的使用习惯:深度兼容:自带方正字体集:在线模板和素材使文档创作更 ...

  7. mysql进阶(十七)Cannot Connect to Database Server

    Cannot Connect to Database Server 缘由 由于不同的项目中使用的数据库用户名与密码出现了不一致的情况,在其中之前较早一个项目执行过程中出现"The user  ...

  8. U盘无法安装win10提示Your PC/Device needs to be repaired

    前一阵子把笔记本自带的win8升级到8.1,又升级到win10. 差不多有一个月没有开机,前几天开机后进不了系统,出现如下图的提示.买电脑自带的win8是正版的,但升级到win10后就过期了,也真是坑 ...

  9. C# BarCodeToHTML条码生成类

    来自:http://www.sufeinet.com/forum.php?mod=viewthread&tid=656&extra=page%3D1%26filter%3Dtypeid ...

  10. 2DSprite添加Light照射(Unity3D开发之十六)

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/45534245 ...