在Java语言这种,字符串起着很是重要的做用,字符串的声明和初始化由如下两种状况: 设计模式
1》对于字符串String s1 = new String("abc")语句与String s2 = new String("abc")语句,存在两种引用对象s1,s2,两个内容相同的字符串对象"abc",他们在内存中的地址是不一样的。只要是用到new总会产生新的对象。 函数
2》对于String s1 = "abc"和String s2 = "abc"语句,在JVM中存在一个字符串池,其中存有不少String对象,而且能够被共享使用,s1,s2引用同一个常连池中的对象,其中String采用Flyweight设计模式,当建立一个字符串常量时,例如String s="abc",会首先在字符串常量池中查找是否存在相同的字符串定义,其判断依据是String对象中的equals方法的返回值。若已经定义,则直接引用其定义,此时不须要建立新的对象;若是没有定义,则首先建立对象,而后把他加入到字符串池中,再将他的引用返回。因为字符串是不可变类,一旦建立好了就不可修改,所以字符串对象能够被共享并且不会引发程序的混乱。 spa
具体而言: 设计
String s = "abc"; //把abc放在常量区中,在编译时产生。 对象
String s = "ab"+"c"; //把“ab”+“c”转换成字符串常量“abc”放在常量区中 内存
String s =new String("anc"); //在运行时把abc放在堆中 字符串
例如: string
String s1 = "abc"; //在常量区中存放了一个"abc"的字符串对象 编译
String s2 = "abc";//s2引用常量区中的对象,所以不会建立新的对象。 变量
String s3 = new String("abc");//在堆中建立新的对象
String s4 = new String("abc");//在堆中又建立一个新的对象
为了理解方便,能够吧String s = new String("abc")语句的执行分类两个过程;第一个过程就是新建对象的过程,即new String("abc");第二个过程就是赋值过程,即String s=。因为第二个过程仅仅建立了一个字符串类型的变量,将一个字符串对象的引用赋值给s,所以这个过程当中不会建立新的对象。第一个过程new String("abc")调用String类中的构造方法:
public String(String origin) {
//body
}
在调用这个构造函数时,传入一个字符串常量,所以语句new String("abc")也就等价于"abc"和new String()两个操做了。若在字符串池中不存在abc,则会建立一个新的字符串常量“abc”,并将其添加到字符串池中;若存在则不建立,而后new String()会在堆中建立一个新的对象,因此s3和s4是指向不一样的String对象,地址天然也就不一样了。如图所示.
引伸:对于string类型的变量s,赋值语句s=null与s=""是否相同?
对于赋值语句s=null,其中s是一个字符串类型的引用,它不指向任一个字符串。而赋值语句s=""中的s是一个字符串类型的引用,它指向另外一个字符串(这个字符串的值为"",也就是空字符串),所以两则是不相同的。
常见的笔试题:
new String("abc")建立了几个对象?
answer:一个或者两个。若是常量池中原来有字符串"abc",那么只建立一个对象;若是常量池中没有字符串"abc",那么就建立两个对象(这两个对象分别位于字符串常量池和堆中)。
最后吐槽:为何答,案二字会被审核不经过呢?想不明白