`
tianlihu
  • 浏览: 311110 次
  • 性别: Icon_minigender_1
  • 来自: 石家庄
社区版块
存档分类
最新评论

java对String字符串对象的创建以及管理

阅读更多
原文链接

  Constant Pool常量池的概念:
  在讲到String的一些特殊情况时,总会提到String Pool或者Constant Pool,但是我想很多人都不太明白Constant Pool到底是个怎么样的东西,运行的时候存储在哪里,所以在这里先说一下Constant Pool的内容。
  String Pool是对应于在Constant Pool中存储String常量的区域.习惯称为String Pool,也有人称为String Constant Pool.好像没有正式的命名。
  在java编译好的class文件中,有个区域称为Constant Pool,他是一个由数组组成的表,类型为cp_info constant_pool[],用来存储程序中使用的各种常量,包括Class/String/Integer等各种基本Java数据类型,详情参见The Java Virtual Machine Specification 4.4章节。
  对于Constant Pool,表的基本通用结构为:
cp_info {
 u1 tag;
 u1 info[];
}

  tag是一个数字,用来表示存储的常量的类型,例如8表示String类型,5表示Long类型,info[]根据
  类型码tag的不同会发生相应变化。
  对于String类型,表的结构为:
CONSTANT_String_info {
 u1 tag;
 u2 string_index;
}

  tag固定为8,string_index是字符串内容信息,类型为:
CONSTANT_Utf8_info {
 u1 tag;
 u2 length;
 u1 bytes[length];
}

  tag固定为1,length为字符串的长度,bytes[length]为字符串的内容。
  (以下代码在jdk6中编译)
  为了详细理解Constant Pool的结构,我们参看一些代码:
String s1 = "sss111";
String s2 = "sss222";
System.out.println(s1 + " " + s2);

  由于"sss111"和"sss222"都是字符串常量,在编译期就已经创建好了存储在class文件中。
  在编译后的class文件中会存在这2个常量的对应表示:
  08 00 11 01 00 06 73 73 73 31 31 31 08 00 13 01 ; ......sss111....
  00 06 73 73 73 32 32 32 ; ..sss222
  根据上面说的String常量结构,我们分析一下:
  开始的08为CONSTANT_String_info结构中的tag,而11应该是它的相对引用,01为CONSTANT_Utf8_info的tag,06为对应字符串的长度,73 73 73 31 31 31为字符串对应的编码,接着分析,会发现后面的是对应"sss222"的存储结构。
  经过上面分析,我们知道了11和13是两个字符串的相对引用,就可以修改class文件来修改打印的内容,把class文件中的00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 12 4D改成00 6E 00 04 00 03 00 00 00 24 12 10 4C 12 10 4D,程序就会输出sss111 sss111,而不是和原程序一样输出sss111 sss222,因为我们把对"sss222"的相对引用12改成了对"sss111"的相对引用10。
public class Test {
 public static void main(String[] args) {
  String s1 = "sss111";
  String s2 = "sss111";
 }
}

  在上面程序中存在2个相同的常量"sss111",对于n个值相同的String常量,在Constant Pool中只会创建一个,所以在编译好的class文件中,我们只能找到一个对"sss111"的表示:
  000000abh: 08 00 11 01 00 06 73 73 73 31 31 31 ; ......sss111
  在程序执行的时候,Constant Pool会储存在Method Area,而不是heap中。
  另外,对于""内容为空的字符串常量,会创建一个长度为0,内容为空的字符串放到Constant Pool中,
  而且Constant Pool在运行期是可以动态扩展的。
  关于String类的说明
  1.String使用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不能再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的(immutable)。
  2.String类有一个特殊的创建方法,就是使用""双引号来创建.例如new String("i am")实际创建了2个
  String对象,一个是"i am"通过""双引号创建的,另一个是通过new创建的.只不过他们创建的时期不同,
  一个是编译期,一个是运行期!
  3.java对String类型重载了+操作符,可以直接使用+对两个字符串进行连接。
  4.运行期调用String类的intern()方法可以向String Pool中动态添加对象。
  String的创建方法一般有如下几种
  1.直接使用""引号创建;
  2.使用new String()创建;
  3.使用new String("someString")创建以及其他的一些重载构造函数创建;
  4.使用重载的字符串连接操作符+创建。

例1
String s1 = "sss111";
//此语句同上
String s2 = "sss111";
System.out.println(s1 == s2); //结果为true


例2
String s1 = new String("sss111");
String s2 = "sss111";
System.out.println(s1 == s2); //结果为false


例3
String s1 = new String("sss111");
s1 = s1.intern();
String s2 = "sss111";
System.out.println(s1 == s2);


例4
String s1 = new String("111");
String s2 = "sss111";
String s3 = "sss" + "111";
String s4 = "sss" + s1;
System.out.println(s2 == s3); //true
System.out.println(s2 == s4); //false
System.out.println(s2 == s4.intern()); //true


例5
  这个是The Java Language Specification中3.10.5节的例子,有了上面的说明,这个应该不难理解了
package testPackage;
class Test {
 public static void main(String[] args) {
  String hello = "Hello", lo = "lo";
  System.out.print((hello == "Hello") + " ");
  System.out.print((Other.hello == hello) + " ");
  System.out.print((other.Other.hello == hello) + " ");
  System.out.print((hello == ("Hel"+"lo")) + " ");
  System.out.print((hello == ("Hel"+lo)) + " ");
  System.out.println(hello == ("Hel"+lo).intern());
 }
}
class Other {
 static String hello = "Hello";
}

package other;

public class Other {
 static String hello = "Hello";
}

  输出结果为true true true true false true,请自行分析!
  结果上面分析,总结如下:
  1.单独使用""引号创建的字符串都是常量,编译期就已经确定存储到String Pool中;
  2.使用new String("")创建的对象会存储到heap中,是运行期新创建的;
  3.使用只包含常量的字符串连接符如"aa" + "aa"创建的也是常量,编译期就能确定,已经确定存储到String Pool中;
  4.使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中;
  5.使用"aa" + s1以及new String("aa" + s1)形式创建的对象是否加入到String Pool中我不太确定,可能是必须调用intern()方法才会加入,希望高手能回答!
  还有几个经常考的面试题:
1.
String s1 = new String("s1") ;
String s2 = new String("s1") ;

  上面创建了几个String对象?
  答案:3个 ,编译期Constant Pool中创建1个,运行期heap中创建2个.

2.
String s1 = "s1";
String s2 = s1;
s2 = "s2";

  s1指向的对象中的字符串是什么?
  答案: "s1"




分享到:
评论

相关推荐

    Java程序设计基础:创建String字符串.pptx

    掌握String字符串对象的创建 掌握字符串对象的输入与输出 一般程序需要处理大量文本数据Java语言的文本数据被保存为字符或字符串类型。 若干个字符在计算机里面如何存储? 如何引用呢? 引入 例如 ...

    JAVA字符串

    Java中将字符串作为String类型对象来处理。当创建一个String对象时,被创建的字符串是不能被改变的。每次需要改变字符串时都要创建一个新的String对象来保存新的内容。原始的字符串不变。之所以采用这种方法是因为...

    GSON包,JAVA对象和LIST转换成JSON字符串

    创建一个 Gson对象在调用其toJson方法将JAVA对象或集合转换成json字符串 Gson gson = new Gson(); String toJson = gson.toJson(Object o);

    Java的String类讲解案例代码(String类使用:创建对象、比较、连接、截取、查找和替换、拆分...)StringBuf

    String类使用(创建字符串对象、比较、长度、连接、截取、查找和替换、切割和拆分、和其他类型的转换、格式化、判断、手动入池、其他操作) StringBuffer类 StringBuilder类 String、StringBuffer和StringBuilder的...

    JAVA 中的字符串处理及类的应用

    JAVA 中的字符串处理及类的应用,希望能帮助到你们。

    Java String 类.pdf

    由于String类是不可变的,对字符串进行操作时需要创建新的字符串对象,这可能会导致性能问题。StringBuilder类是可变的,可以避免这种问题,因此它的性能比String类更好。 三、String类和StringBuffer类有什么区别?...

    java实验一 图形 字符串 复数

    4、 给定的字符串数组:strings s[] = {“string”,”starting”,”strong”,”street”,”stir”,”studeng”,”soft”,”sting”},编写应用程序,统计以”st”开头的字符串有多少个,以”ng”结尾的字符串有多少个...

    String_字符串.html

    String对象是不可变的。JVM对其做了一个优化,在内存中开辟了一段区域作为字符串常量池。通过"字面量"形式创建的字符串对象都会缓存并重用。

    Java语言程序设计(第3版)第06章-字符串.pptx

    创建字符串对象 Java语言程序设计(第3版) Java语言程序设计(第3版)第06章-字符串全文共31页,当前为第4页。 6.1.1 字符串基本操作 Java语言程序设计(第3版) 字符串在内存的表示。设有下面声明: String str = new ...

    Java高级程序设计:第6章-字符串和包装类.pptx

    字符串对象的创建方法;Interned String;Interned String;Interned String;取得字符串的长度;按照位置取得指定字符;遍历字符串;练习;下标越界异常;获取子字符串;获取子字符串;练习;查找字符或子串;查找字符或子串;...

    字符数组的存储方式 字符串常量池.docx

    字符串在java程序中被大量使用,为了避免每次都创建相同的字符串对象及内存分配,JVM内部对字符串对象的创建做了一定的优化,在Permanent Generation中专门有一块区域用来存储字符串常量池(一组指针指向Heap中的...

    Java学习笔记(六)–字符串String类

    文章目录字符串一、String 类1.1 声明字符串1.2 创建字符串二、连接字符串2.1 连接多个字符串2.2 连接其他数据类型三、获取字符串信息3.1 获取字符串长度3.2 字符串查找3.3 获取指定索引位置的字符四、字符串操作4.1...

    javaString.docx

    Java-String类的常用方法总结,String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象。java把String类声明的final类,不能有类。String类对象创建后不能修改,由0或多个字符组成,包含...

    string类的常用方法.pdf

    它是不可变的,也就是说一旦创建了一个字符串对象,它的值就不能被修改。字符串类提供了许多方法来操作字符串,包括拼接、比较、截取和搜索等。 可以使用字符串字面值来创建字符串对象,例如: String str = ...

    浅谈javascript和java中的字符串

     一、字符串的创建  创建一个字符串有几种方法。  1、简单的是用引号将一组字符包含起来 var myStr = "Hello, String!";// 在js中单双引号没有区别  2、可使用如下语句:var myStr1 = new String("Hello,...

    javascript中数组(Array)对象和字符串(String)对象的常用方法总结

    (1)字符串对象的创建 例1: var str="Hello world"; 或者 var str=new String("Hello world") (2)charAt()方法 charAt()方法用于返回指定位置的字符串,比如我们想返回str字符串中,第二个字符,则可以写成...

    实验05 Java集合.doc

    2)按顺序往集合中添加5个字符串对象:"张三"、"李四"、"王五"、"马六"、"赵七"; 3)对集合进行遍历,分别打印集合中的每个元素的位置与内容; 4)打印集合的大小,然后删除集合中的第3个元素,并显示删除元素的...

    Java对象创建方式及JVM对字符串处理

     在讲Jvm对字符串的处理之前,我们先来讲一下,在Java中,常见的5种创建对象的方式:  1)通过关键字new调用构造器创建Java对象,eg:String str = new String("hello");  2)通过Class对象的newInstance()...

    Java-SE中的String世界.pptx.pptx

    String类提供了多种构造方法,用于创建不同类型的字符串对象,包括直接赋值、字符数组、字节数组等。 常用的String构造方法 常用的String构造方法有直接赋值、字符数组构造和字节数组构造,这些方法能够快速创建出...

Global site tag (gtag.js) - Google Analytics