Java--String

一:常量池:
在java编译好的class文件中,有个区域称为Constant Pool,他是一个由数组组成的表,类型
为cp_info constant_pool[],用来存储程序中使用的各种常量,包括Class/String/Integer等各种基本Java数据类型

虚拟机必须为每个被装载的类型维护一个常量池。常量池就是该类型所用常量的一个有序集合,包括直接常量(String ,integer和floating point常量)和对其他类型、字段和方法的符号引用。池中的数据项就像数组一样是通过索引访问的。因为常量池存储了相应类型所用到的所有类型、字段和方法的符号引用,所以它在Java程序的动态连接中起着核心作用

常量池包含了与文件中类和接口相关的常量。常量池中存储了诸如文字字符串、final变量值、类名和方法名的常量。Java虚拟机把常量池组织为入口列表的形式。在实际列表constant_pool之前,是入口列表中的技术constant_pool_count!

每个常量池入口都从一个长度为一个字节的标志开始,这个标志指出了列表中该位置的常量类型。一旦java虚拟机获取并解析这个标志,Java虚拟机就会知道在标志后的常量类型是什么!

在动态链接的Java程序中,常量池充当了十分重要的角色。除了字面常量(或者说直接量)值以外,常量池还可以容纳下面几种符号引用。
● fully qualified names of classes and interfaces 类和字段的全限定名。
● field names and descriptors 字段的名称和描述符
● method names and descriptors 方法的名称和描述符

对于Constant Pool,表的基本通用结构为:

cp_info {
u1 tag;
u1 info[];
}
常量池是一个可变长度cp_info表的有序序列。Cp_info表中的tag(标志)项是一个无符号的byte类型值,它表明了表的类型和格式cp_info表一共有11中类型。
tag是一个数字,用来表示存储的常量的类型,例如8表示String类型,5表示Long类型,info[]根据
类型码tag的不同会发生相应变化.
二:
String Pool是对应于在Constant Pool中存储String常量的区域!
三:
public class Test {
public static void main(String[] args) {
String s1 = “sss111”;
String s2 = “sss111”;
}
}
注:
1–对于n个值相同的String常量,在Constant Pool中只会创建一个
2–执行的时候,Constant Pool会储存在Method Area,而不是heap中
3–对于”“内容为空的字符串常量,会创建一个长度为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.使用重载的字符串连接操作符+创建

    String s1 = "hello";
    String s2 = "hello";  
  由于String Pool只会维护一个值相同的String对象 
 上面2句得到的引用是String Pool中同一个对象,所以 
 他们引用相等 
    System.out.println(s1 == s2);//true


    String s1 = new String("hello");
    String s2 = "hello";  
由于s1是new出的新对象,存储在heap中,s2指向的对象 
 存储在String Pool中,他们肯定不是同一个对象,只是 
 存储的字符串值相同,所以返回false. 
    System.out.println(s1 == s2);//false


 String s1 = new String("hello");
 String s2 = "hello";
 s1=s1.intern();
当调用intern方法时,如果String Pool中已经包含一个等于此String对象 
的字符串(用 equals(Object)方法确定),则返回池中的字符串.否则,将此 
String对象添加到池中,并返回此String对象在String Pool中的引用.
    System.out.println(s1 == s2);

String s1 = new String(“111”);
String s2 = “sss111”;
/*
* 由于进行连接的2个字符串都是常量,编译期就能确定连接后的值了,
*
* 编译器会进行优化直接把他们表示成”sss111”存储到String Pool中,
*
* 由于上边的s2=”sss111”已经在String Pool中加入了”sss111”,
*
* 此句会把s3指向和s2相同的对象,所以他们引用相同.此时仍然会创建出
*
* “sss”和”111”两个常量,存储到String Pool中.
*/

String s3 = “sss” + “111”;

/*
*
* 由于s1是个变量,在编译期不能确定它的值是多少,所以
*
* 会在执行的时候创建一个新的String对象存储到heap中,
*
* 然后赋值给s4.
*/

String s4 = “sss” + s1;

System.out.println(s2 == s3); // true

System.out.println(s2 == s4); // false

System.out.println(s2 == s4.intern()); // true

结果上面分析,总结如下:
1.单独使用”“引号创建的字符串都是常量,编译期就已经确定存储到String Pool中.
2.使用new String(“”)创建的对象会存储到heap中,是运行期新创建的.
3.使用只包含常量的字符串连接符如”aa” + “aa”创建的也是常量,编译期就能确定,已经确定存储到String Pool中.
4.使用包含变量的字符串连接符如”aa” + s1创建的对象是运行期才创建的,存储在heap中.
6.使用”aa” + s1以及new String(“aa” + s1)形式创建的对象必须调用intern()方法才会加入String Pool!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值