您的位置:首页 > 编程语言 > Java开发

Java String类对象引用、字符串常量和String Pool 相互关系的学习

2014-06-22 16:21 489 查看

Java中的数据类型及其存放的内存位置

栈:存放基本数据类型及对象的引用

堆:new 操作符建立的对象(包括数组)

静态域:static定义的静态成员变量

常量池:存放常量

代码及输出结果及原理解释

public class StringTest
{

/**
* @param args the command line arguments
*/
public static void main(String[] args)
{
String a = "hello";
// 1.栈内存中创建一个String类型的引用变量a;
// 2.在字符串常量池中寻找有没有"hello",如果没有则在字符串常量池中创建对象并将对象的地址赋给a
// 如果有则将地址直接赋给变量a。这里因为字符串常量池中没有"hello",因此需要创建一个新的对象。
// 3.该表达式创建了1个引用1个对象。

String b = "hello";
// 1.栈内存中创建一个String类型的引用变量b;
// 2.在字符串常量池中寻找有没有"hello",如果没有则在字符串常量池中创建对象并将对象的地址赋给b
// 如果有则将地址直接赋给变量a。这里因为字符串常量池中有"hello",因此不需要创建一个新的对象。
// 3.该表达式创建了一个引用。

String newA = new String("hello");
// 1.栈内存中创建一个String类型的引用变量newA;
// 2.在字符串常量池中寻找有没有"hello",如果没有则在字符串常量池中创建对象
// 如果有则将地址直接返回对象引用。
// 3.通过向构造函数传递另外一个字符串对象的引用在堆中创建一个新的对象,并将地址
// 赋给引用变量newA。
String c = "hel";
String d = "lo";
final String finalc = "hel";
// 编译期间能够确定的引用常量,那么编译期间用字符串常量替换该引用。
final String finalgetc = getc();
// 编译期间不能够确定的引用常量。

System.out.println("a == b ? " + (a == b)); // true
// a 和 b 都指向的是String Pool中的"hello"对象。

System.out.println("a == newA ? " + (a == newA)); // false
// newA指向的堆中的"hello"对象

System.out.println("a == hel + lo ? " + (a == "hel" + "lo")); // true
// 编译器会将"hel" + "lo"优化,合成"hello"。

System.out.println("c == finalc ? " + (a == finalc + "lo")); // true
// 编译器会用"hel"替换finalc,因此结果和上一个表达式是一样的。

System.out.println("c == finalc ? " + (a == finalgetc + "lo")); // false
// 由于finalgetc是一个编译期间不能确定的引用,只有在运行期间才能确定。
// 因此它所引用的内容和"lo"相连接,在堆中创建一个新的String 对象。所以两者的
// 地址是不一样的。

System.out.println("a == c + d ? " + (a == c + d)); // false
// 道理同上。

System.out.println("finalgetc == finalc ? " + (finalgetc == finalc)); // true
// 两者所指向的都是String Pool中"hel"的地址。

// String::intern()函数的含义:当调用 intern 方法时,如果池已经包含一个
// 等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回
// 池中的字符串。否则,将此String 对象添加到池中,并且返回此String 对象的引用
System.out.println("a.intern() == b.intern()"+ (a.intern() == b.intern())); // true
// a调用intern()和b调用intern() 方法返回的都是String Pool 中的"hello"的地址

System.out.println("a.intern() == b.intern()"+ (a.intern() == newA.intern())); // true
// 当a调用intern()和newA调用intern() 方法返回的都是String Pool 中的"hello"的地址

System.out.println("a.intern() == b.intern()"+ (newA == newA.intern())); // false
// newA调用intern() 方法返回的都是String Pool 中的"hello"的地址,newA指向的是堆中的对象。
}

private static String getc()
{
return "hel";
}
}


程序运行结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息