1.String存储类型:引用数据类型
String类型与数组类似,属于引用数据类型。在Java中,是通过创建对象存储其地址的形式来指向具体的字符串。在JDK8之前,字符串本身是存储在JVM的方法区的字符串常量池中。(JDK8以后存储在堆内存中)
2.String创建方式
(1)静态创建
String a1="this is a String!"
创建方式如上图。在创建String类型的变量的时候建议使用直接赋值的方法去创建对象,在多个变量使用同一个字符串的时候,会指向通一块字符串(即存储地址相同)字符串会放在常量池当中(常量池是堆内存中的一块特殊区域–常量池的位置变化在文末),不管创建多少个对象,都是引用的常量池的那个字符串。
(2)动态创建
String a2=new String("this is a string");
创建方式如上图,运用String类的构造方法进行创建。主义,采用new 的方法的话,创建出来的变量是放在栈内存中,每个实际对象都会在堆中开辟出新的内存空间来完成储存,不管字符串是否一致。
(3)图解两种创建方式的异同
String s1="abcdef";
String s2="abcdef"+"xy";//字符串间可用“+”拼接
String s3=new String("abcdefxy");
由图可知,我们通过静态创建方法来创建s1和s2变量,用动态创建方法new出一个s3对象来指向字符串常量池。不难发现,对于s1和s2,其引用是直接指向方法区中的字符串常量池的。
而s3则不同,通过new的对象,在堆中有了一个实例后,再通过该实例指向字符串常量池中相应的字符串,相较于静态创建,相当于是多了一个“中间商”进行指向。
为了更加具体的区分其异同,这里我们都以“aa”字符串作为代表。通过上图可知,通过String构造方法new出的对象s、s1、s2是独立开的三个对象(想想是为什么呢?)答案很简单,我们在栈内存中声明的类型是指向堆中创建出的三个不同地址的对象,而这三个不同的对象各自在不同的地址,即使这三个对象指向的又是同一个地址,它们也已经是不同的了。这里可能有点绕,缓缓可以想明白。
然后我们再来看直接赋值方法创建,不难发现,s、s1和s2指向了常量池中的“aa”,所以可以这样认为,它们指向了同样的地址,即s1==s2==s3(除了变量名,其余全都相同)。
通过上述,留给读者一个思考题作为自测:
String s1="abc";
String s2="abc";
String s3=new String("abc");
//问:该过程一共创建了多少对象,试着用上述图解的方法答出来。