Java中的字符串问题
本文章分为三个部分:
1、创建字符串对象的两种方式以及它们的存储方式
2、String a = new String("a")创建了几个对象的问题
3、字符串小例子
----------------------------------------------我是友好的分隔线----------------------------------------------
在《Java核心技术I》中对String类的描述就是“由于不能修改Java字符串中的字符,所以在Java文档中将String类对象称为不可变字符串......编译器可以让字符串共享”。可是在哪里可以实现“共享”这个操作呢?字符串池。
我们知道创建一个字符串对象有两种方式:1) 采用字面值的方式赋值 2) 采用new关键词新建一个字符串对象。
方式一:采用字面值的方式赋值
首先我们先举个小例子:
public class StringTest { public static void main(String[] args) { String a = "aaa"; String b = "aaa"; } }
一般的做法是直接用System.out.println(a==b);来判断,此处用javap -v反编译的方式来判断a和b的值是不是来自同一个地方。
这里的ldc的含义是:将常量值从常量池中取出来并且压入栈中。
我们可以看到,a和b是指向同一个字符串对象的,因为"aaa"这个字符串对象在字符串池中,而字符串池是常量池的一种,而且我们可以从"LocalVariableTable"得知,在编译期间,a和b的值就已经确定好了。如果想要创建一个字符串对象,编译器会先在字符串池中查找是否有相同字符串的对象,如果有,就可以直接指向这个对象(多个变量可共享同一个对象),如果没有,那就创建一个新的字符串对象。
方式二:采用new关键词新建一个字符串对象
还是先举一个小例子:
public class StringTest { public static void main(String[] args) { String a = new String("bbb"); String b = new String("bbb"); } }
用javap -v反编译之后得到:
我们可以看到,这里既有用在字符串池创建的对象的方式(红色),也有调用String类并启用来创建对象(绿色)。其实在使用new关键词创建字符串对象的流程是这个样子的:JVM会先在字符串池中寻找"bbb"这个对象,如果有,就不会在字符串池中创建这个对象,而且直接在堆创建“bbb”这个字符串对象,并将这个对象的地址返回给a;如果没有,则会先在字符串池中创建"bbb"对象,然后再在堆中创建"bbb”这个对象并把这个对象的地址返回给a。因为a和b都是分别new了一个字符串对象,所以它们的字符串对象的地址是不同的。但是我们可以从"LocalVariableTable"中可以看到,a和b变量在字符串池中的对象是在编译期间就已经创建好了,但是因为a和b的字符串对象是用new的方式创建的,所以,a和b的创建需要在运行的时候才能全部完成。
总而言之,无论是用哪种方式创建字符串对象,都需要在字符串池中进行字符串对象的创建,如果是用new关键词创建对象的话,还需要在堆中创建对象并将对象的地址返回给变量。
----------------------------------------------我是友好的分隔线----------------------------------------------
有一道面试题是这样子的,“String a = new String("a")”是创建了几个对象?
其实,这道题可以用我们上面对字符串创建的分析来作答:创建了一个或者两个对象。
这里给两个提示:1) String a = new String("a"); 2) String a = "a"; String b = new String("a");
具体要怎么分析可以参考这篇文章https://blog.csdn.net/limingchuan123456789/article/details/14150327,不过只要理解了上面的分析,这道题解答起来并不难。
----------------------------------------------我是友好的分隔线----------------------------------------------
下面是关于字符串的一些小例子,看看都能做对吗?
public class StringTest { public static void main(String[] args) { String a = new String("aaa"); String b = "aaa"; String c = "a"+new String("aa"); String d = "a"+"aa"; System.out.println(a==b); System.out.println(a==c); System.out.println(b==c); System.out.println(b==d); System.out.println(c==d); } }
答案是:
false false false true false
参考:
https://www.cnblogs.com/fangfuhai/p/5500065.html
https://blog.csdn.net/limingchuan123456789/article/details/14150327