一、java内存分配
1、结构
2、举例
二、代码
直接上代码
public class Stringbasics {
public static void String1() {
String b = "b";
String ab = "ab";
String ab1 = "a" + "b";
String ab2 = "a" + b;
/* ab和ab1在常量池上是同一份字符串常量,a和b同时指向“ab”,
两个指向的内存空间相同*/
System.out.println(ab == ab2);//false
/*字符串变量ab指向常量池中的“ab”,而表达式中ab2=“a”+b的b是字符串变量,
所以字符串变量b不能存储在字符串常量池中,要在堆中新建一个字符串对象存储“b”,两个指向的内存空间不同!!!因此输出false*/
System.out.println(ab == ab1);//true
}
//final定义字符串时为字符串常量
public static void String2() {
String a = "ab";
final String bb = "b";
String b = "a" + bb;
// 因为final定义了bb为字符串常量,因此表达式b= “a”+bb是确定的,因此a和b同时指向字符串常量池中的“ab”
System.out.println(a == b);//true
}
/*因为getBB()相当于newString(“b”);在堆内存中创建了对象,
所以b指向的是堆内存中的对象,而a指向的是字符串常量池中的字符串,
所以两个指向的不是同一个“ab”,因此输出false*/
public static void String3() {
String a = "ab";
final String bb = getBB();
String b = "a" + bb;
System.out.println(a == b);//false
}
private static String getBB() {
return "b";
}
/*第一个输出是false,原因:a是指向字符串常量池中“ab”的变量,
而s=s1+ s2,s1和s2是变量,是不确定的,不能再存储在字符串常量池中,
而是存储在堆中新建的字符串对象,因此a和s指向的不是同一个字符串*/
/*第二个输出结果是true。原因当String调用intern方法时,
如果池中已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。
否则,将此String对象添加到池中,并返回此String对象的引用。两个变量指向的是同一个“ab”!!*/
private static String a = "ab";
public static void String4() {
String s1 = "a";
String s2 = "b";
String s = s1 + s2;
System.out.println(s == a); //false
System.out.println(s.intern() == a);//true
}
/*第一个输出是false。aa是在堆中分配的对象字符串“ab”,而s是在堆中新建一个对象存储字符串,所以两个变量指向不同的内存空间
第二个输出是false,s.intern()将字符串添加到常量池中了,而aa还是指向堆空间的引用,因此两个字符串变量指向的是不同的内存空间
第三个输出true,s.intern()和aa.intern()都是将堆中的字符串添加到字符串常量池中,在常量池中维护的是同一份数据,
因此两个指向的是同一个字符串常量“ab”,所以输出true
*/
private static String aa = new String("ab");
public static void String5() {
String s1 = "a";
String s2 = "b";
String s = s1 + s2;
System.out.println(s == aa);//false
System.out.println(s.intern() == aa);//false
System.out.println(s.intern() == aa.intern());//true
}
public static void main(String[] args) {
String1();
String2();
String3();
String4();
String5();
}
}