[关闭]
@frank-shaw 2015-10-29T10:40:12.000000Z 字数 1415 阅读 1955

String类与常量池

java.基础知识


String类型

String的一个很重要的特点:String是值不可变的常量,是线程安全的。接下来,String类使用了final修饰符,表明了String类的第二个特点:String类是不可继承的。
下面是String类的成员变量定义,从类的实现上阐明了String值是不可变的。

private final char value[];
private final int count;

那既然String变量是不可变的,那么对于String类中的concat方法(将另外字符串拼接到该字符串后面)该如何解释呢?实际上是生成了一个新的String类对象,复制了原来的数据信息而已。

“对String对象的任何改变都不影响到原对象,相关的任何change操作都会生成新的对象”。

常见问题1:String str="hello world"和String str=new String("hello world")的区别

问了解答这个问题,首先需要知道常量池的概念:在class文件中有一部分 来存储编译期间生成的 字面常量以及符号引用,这部分叫做class文件常量池,在运行期间对应着方法区的运行时常量池。

因此在上述代码中,String str1 = "hello world";和String str3 = "hello world"; 都在编译期间生成了 字面常量和符号引用,运行期间字面常量(确定的不变的值)"hello world"被存储在运行时常量池(当然只保存了一份)。通过这种方式来将String对象跟引用绑定的话,JVM执行引擎会先在运行时常量池查找是否存在相同的字面常量,如果存在,则直接将引用指向已经存在的字面常量;否则在运行时常量池开辟一个空间来存储该字面常量,并将引用指向该字面常量。

众所周知,通过new关键字来生成对象是在堆区进行的,而在堆区进行对象生成的过程是不会去检测该对象是否已经存在的。因此通过new来创建对象,创建出的一定是不同的对象,即使字符串的内容是相同的。

常见问题2:String、StringBuffer、StringBuilder的区别

有了String,为什么还需要后面这两个家伙呢?其实呀,就是因为String不可变的特性,导致了StringBuffer、StringBuilder的产生。由于String每一次变化的时候都会产生一个新的对象,有些时候是必要的,有些时候就是不必要的而且会导致很大的内存浪费,这个时候就要使用StringBuffer、StringBuilder来帮忙弥补啦。

那么StringBuffer、StringBuilder之间有什么区别呢?
1.StringBuffer是线程安全的,前面有synchronized关键字,吊得很不跟他玩;相比之下,StringBuilder就不是线程安全的啦。

运行时常量池

运行时常量池相对于Class文件常量池的另外一个重要特征就是具备动态性,Java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的变量放入池中。一个非常典型的例子就是String类的intern()方法:

String.valueOf(500).intern();

既然运行时常量池是方法区的一部分,自然受到方法区内存的限制,当常量池无法再申请到内存时会抛出OutOfMemoryError异常。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注