String str = "abc";和String str =new String("abc");到底分别创建了几个对象?

一、到底创建了几个对象
1、String str = “abc”; 创建了几个对象?0个 或者 1个

2、String str = new String(“abc”);创建了几个对象? 1个或2个

二、首先了解几个基本的概念: 点击了解 JVM的内存管理
1、String是一个特殊的包装类数据。即可以用String str = new String(“abc”);的形式来创建,也可以用String str = “abc”;的形式来创建。

2、JVM的堆中存放对象的实例,而JVM的栈中存储对象的引用。

3、字符串常量池:第二部分参考文章
a、字符串的分配和其它对象一样,是需要消耗高昂的时间和空间的,而且字符串我们使用的非常多,JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池每当我们创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性我们可以十分确定常量池中一定不存在两个相同的字符串。

b、Java中的常量池,实际上分为两种形态:静态常量池运行时常量池
静态常量池:即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串(数量 )字面量,还包含类、方法的信息,占用class文件绝大部分空间。
运行时常量池:则是jvm虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

三、String对象的创建过程:第三部分参考文章
a、String str = “abc”;创建过程:
1、首先在常量池中查找是否存在内容为"abc"字符串对象。
2、如果不存在则在常量池中创建"abc",并让str引用该对象。(也就是创建1个对象的情况)
3、如果存在则直接让str引用该对象(该对象是存在方法区的运行时常量池中的)。(也就是创建0个对象的情况)
String str =
b、String str = new String(“abc”);创建过程:
1、首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象。(创建第1个对象)
2、在字符串常量池中查看是否存在内容为"abc"的字符串对象。
3、若存在,则让堆中创建好的字符串对象对字符串常量池的对象进行引用。(也就是只创建1个对象的情况)
4、若不存在,则在常量池中添加一个内容为"abc"的字符串对象,并将堆中的String对象进行引用。(也就是创建2个对象的情况)
String str =
c、下面代码结果为true,说明同为常量池中的一个对象:

String str = "abc";
String str1 = "ab" + "c";
System.out.println(str == str1); //true

因为String str1 = “ab” + “c”;会查找常量池中是否存在内容为"abc"的对象,如果存在则直接让str1引用该对象,因为String str = “abc”;已经在常量池中创建了abc对象,所以str1直接引用该对象,str == str1;

d、下面代码结果为false,说明产生了新的对象:

String str1 = "abc";
String str2 = "ab"; 
String str3 = str2 + "c"; 
System.out.println(str1 == str3);	//false

因为String str3 = str2 + "c"涉及到变量(不全是常量)的相加,所以会产生新的对象,其内部实现是先new一个StringBuffer,然后append(str2)再append(“c”),然后让str3引用toString返回的对象。

相信只要你理解了上面的内容,以后在面试的过程中,不论遇到关于String创建对象的什么情况,你都可以应对自如。

你要去做一个大人,不要回头,不要难过。

“今天起了风,你站在风口,我的整个世界都是你的味道。”

你可能感兴趣的:(Java相关)