首先,我们要谈到JAVA中字符串存储的空间,主要用到下面三块(PS:整个JAVA运行时的内存空间不止这三块,有兴趣可以自己去了解):
1.堆:存放程序运行中生成的对象等数据的区域,如String str = new String("Blog");其中"Blog"这个值就是存放在堆中的。
2.栈:存放基本类型,如int a=3;还有存放对象的引用,如String str = new String("Blog")中的str存放于栈中。
3.方法区中的常量池:包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式,其中的"java"字符串是存放于常量池中的,而s是存放于栈中。
系统打印输出为"true",原因很简单,因为"Java","Study"等字符串是一个确定的字符串,在编译时已经加入了常量池中,只要内容的值相同,对象的引用指向的都是同一个字符串,所以用"=="运算符比较str3 和 str4 这两个对象的引用时,由于所指向的地址相等,都是是常量池中的同一块内存空间,所以返回"true"。(栈中存放对象的引用)
理由:
第一个输出,第二个输出:str5在编译时并不知道str2的地址(地址是在运行时分配的),所以并不能通过str2知晓其字符串的值,只有在程序运行时才可以得知,是运行时才生成的,所以其字符串并不是放入常量池中,而是放入堆内存中,所以调用"=="运算符对其进行比较时,会返回"false",因为指向的并不是同一个内存块,同理,str6在编译时也并不知道str2和str1的地址,返回"false"。
第三个输出:String.equals()方法比较的是两个String对象中的属性内容是否相同,由于str6和str4只是指向的地址不一样,其中的属性内容是完全相同的,所以返回值为"true"。
第四个输出:虽然str6的对象,str5的对象都是存放在堆中的,而且内容相同,但是正如上文所说的,编译时并不知道str1,str2里的内容,所以运行时还是各自生成了一块内存空间存放各自的对象。
输出结果为"false","false","false"。
1.堆:存放程序运行中生成的对象等数据的区域,如String str = new String("Blog");其中"Blog"这个值就是存放在堆中的。
2.栈:存放基本类型,如int a=3;还有存放对象的引用,如String str = new String("Blog")中的str存放于栈中。
3.方法区中的常量池:包括了关于类,方法,接口等中的常量,也包括字符串常量,如String s = "java"这种申明方式,其中的"java"字符串是存放于常量池中的,而s是存放于栈中。
还有,了解一下"=="运算符以及String类中equals()的用法,"=="运算符用来判断基本类型时(int,double等),比较的是值的大小是否相等,当"=="用来比较对象的引用时(如String s = "java"中的s),那么,比较的是对象引用所指向的地址是否一致,而String类中equals()方法是,当X.equals(Y)中X,Y是同一类对象且属性内容相同时,返回true,否则返回false。
public static void main(String[] args) {
// TODO Auto-generated method stub
//字符串存于常量池中
String str1="Java";
String str2="Study";
String str3="Java"+"Study";
String str4="JavaStudy";
System.out.println(str3==str4);
系统打印输出为"true",原因很简单,因为"Java","Study"等字符串是一个确定的字符串,在编译时已经加入了常量池中,只要内容的值相同,对象的引用指向的都是同一个字符串,所以用"=="运算符比较str3 和 str4 这两个对象的引用时,由于所指向的地址相等,都是是常量池中的同一块内存空间,所以返回"true"。(栈中存放对象的引用)
//字符串存于堆中
String str5="Java"+str2;
String str6=str1 + str2;
String str7=str3;
System.out.println(str3==str6);
System.out.println(str3==str5);
//equals()方法比较存于常量池中的str4和存于堆中的str6
System.out.println(str4.equals(str6));
System.out.println(str6==str5);
System.out.println(str7==str6);
理由:
第一个输出,第二个输出:str5在编译时并不知道str2的地址(地址是在运行时分配的),所以并不能通过str2知晓其字符串的值,只有在程序运行时才可以得知,是运行时才生成的,所以其字符串并不是放入常量池中,而是放入堆内存中,所以调用"=="运算符对其进行比较时,会返回"false",因为指向的并不是同一个内存块,同理,str6在编译时也并不知道str2和str1的地址,返回"false"。
第三个输出:String.equals()方法比较的是两个String对象中的属性内容是否相同,由于str6和str4只是指向的地址不一样,其中的属性内容是完全相同的,所以返回值为"true"。
第四个输出:虽然str6的对象,str5的对象都是存放在堆中的,而且内容相同,但是正如上文所说的,编译时并不知道str1,str2里的内容,所以运行时还是各自生成了一块内存空间存放各自的对象。
第五个输出:str7 直接声明了对str6对象的引用,所以与str6指向的是同一块内存空间。所以str6==str7的返回值为true。
String str8=new String("JavaStudy");
String str9=new String(str2);
String str10=new String("JavaStudy");
System.out.println(str9==str3);
System.out.println(str8==str9);
System.out.println(str8==str10);
}
输出结果为"false","false","false"。
new String方法会生成一个新的对象,即使声明指向一个已有的对象,或者是一个堆中已有的字符串,所以在使用"=="运算符时,由于str3,str8,str9,str10指向的内存块都各不相同,所以程序返回三个"false"。
本人为初学者,理解水平有限,如有错误,还望各位斧正。