string三问:Java中如何给字符串分配内存
zrd 2008-08-20 06:05:38 今天研究了一下Java中字符串内存分配的问题,但仍然没有弄清楚,希望有高手指教一下
String是一个特殊的包装类数据。可以用:
String str = new String("abc");
String str = "abc";
两种的形式来创建,第一种是用new()来新建对象的,它会在存放于堆中。每调用一次就会创建一个新的对象。而第二种是先在栈中创建一个对String类的对象引用
变量str,然后查找栈中有没有存放"abc",如果没有,则将"abc"存放进栈,并令str指向”abc”,如果已经有”abc” 则直接令str指向“abc”。
比较类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==,下面用例子说明上面的理论。
代码片段(一)
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true 这里
System.out.println(str1.equals(str2)); //true too.
可以看出str1和str2是指向同一个对象的。
代码片段(二)
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1.equals(str2)); //true 毫无疑问,这里证明他们是堆中的两个对象。
System.out.println(str1==str2); // false
用new的方式是生成不同的对象。每一次生成一个。
因此用第二种方式创建多个”abc”字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度,因
为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符
串值是否相等,是否有必要创建新对象,从而加重了程序的负担。
以上转自网络
疑问1:
String str1 = "abc";这样创建的 字符串 str1和str2,适用 ==可以理解为指向栈中的同一块内存,适用equals()方法又可以理解为堆中的对象。那么它到底是
在堆中的呢,还是在栈中的呢。难道这就是他的特殊之处吗?
代码片段(三)
Integer str1 = new Integer(12345);
Integer str2 = new Integer(12345);
if(str1.equals(str2))
System.out.println("equals right"); //这里输出正确
if(str1==str2)
System.out.println("== right"); //这里没有输出
当测试两个包装类的引用是否指向同一个对象时,应用equals()方法而非==,可见包装类创建的是堆中的对象。
疑问2:
代码片段(四)
String str1 = "string";
String str3 = "str";
String str4 = "ing";
String str2 = str3+str4;
if(str1.equals(str2))
System.out.println("equals right"); //这里输出正确
if(str1==str2)
System.out.println("== right"); //这里没有输出
由此可见,(一)中虽然定义了两个字符串str1 and str2,但实际上在栈中只有一个"abc",而str1 和 str2两个引用变量同时指向这个字符串,所以可以用“==”
来判断是否相等。而(四)中的str1和str2并不是指向共同的字符串,所以不能用“==”来判断。那么为什么可以用equals()方法判断呢,如果理解为String
str1 ="string"; 就是在堆里面创建的,就可以了,但是堆里的对象又不能用“==”判断,所以还是解释不清楚。
疑问3:
代码片段(五)
String str1 = new String( "string");
String str3 = "str";
String str4 = "ing";
String str2 = str3+str4;
if(str1.equals(str2))
System.out.println("equals right"); //这里输出正确
if(str1==str2)
System.out.println("== right"); //这里没有输出
两种不同方式创建的字符串竟然存在着某种联系!看来问题越来越复杂了!
补充一个问题:
equals方法,默认实现就是用"=="来直接比较内存地址:
Object.equals:
public boolean equals(Object obj) {
return (this == obj);
}
那么str1==str2 与str1.equals(str2) 的不同之处又是什么呢?
请高手指教!