日期:2014-05-20  浏览次数:20559 次

请大家进来指点一下吧,今天我真的搞晕了.
class   A
{
public   static   void   main(String   []   args)
{
String   a= "my ";
String   b= "my ";
System.out.println(a==b);//此处.输出true;我不明白,String为引用类型啊?
//如果借用c++的思想来说:a,b分别为一个一级指针.a代表内存中的一个地址,同样
//b也代表内存中的一个地址,此时怎么会相等呢?应当输出false才对啊?
}
}


------解决方案--------------------
to sureyor:

public static void testString(){
String a = new String( "abc ");
String b = "abc ";
System.out.println(a==b);
}
输出是false。我看了楼上一位的话了,String b = "abc ";是在编译时作为常量池写入的,故实际b的那个 "abc ",在a的那个 "abc "出生之前就已经出生了,只是比较慢进入内存里而已,看来我理解中的内存查找是错的,应该是编译期查找了。
你后面还说“按照这个理论,用=进行赋值效率是很低的,还不如new来得快?”,new的作用是初始化,即调用构造器,赋值指的是将一个对象的内存引用地址告诉另一个引用,和初始化是两个过程。我猜你问的是常量赋值吧,即= "ss ";或=(int)12;对复杂对象的不用考虑,对基本数据类型的不需要考虑(因为它们是栈存储,不是对象的堆存储),特例其实只有String这样的,它跟基础数据类型关系密切,可以作为常量池变量。类对象初始化过程中,它们作为常量池先被初始化,基础数据类型到栈离去,String到堆里去,而象new String( "abc ")这样的,在常量初始化之后才开始初始化,而且在内存中,不查找之前是否已存在了这样的对象,我再说一遍,是在编译期查找,不然java就慢死了。

以下归纳了几句,new是唯一的初始化过程,它让构造器执行了。
赋值是赋引用的过程,仅仅是把一个引用的值改成另一个,指向了另一个对象。


to longyuxinxinxin:

java中不会对同一变量两次声明,所以你的
String a= "abc ";
String a= "bcd ";

String a= "abc ";
a= "bcd ";
意思吧,如果不是,那编译就限制它通不过了,不讨论。

如果是,
a是一个引用,它的值指向内存中的对象地址,故a被赋值是它引用的值指向了其他对象的地址。
a==a,比较的是它引用的值。


------解决方案--------------------
我记得以前看过孙鑫老师的书还是教学笔记上说的蛮清楚的,下面有3个例子,请自己悟解吧.
public class Equivalence{
public static void main(String args[]){
Integer n1=new Integer(47);
Integer n2=new Integer(47);
System.out.println(n1==n2);
System.out.println(n1!=n2);
}
}


//先false后true. 是比较对象的引用而不是对象的内容
public class EqualsMethod1{
public static void main(String args[]){
Integer n1=new Integer(47);
Integer n2=new Integer(47);
System.out.println(n1.equals(n2));
}
}

//true. 是比较对象的内容而不是对象的引用

class Value{
int i;
}

public class EqualsMethod{
public static void main(String args[]){
Value v1=new Value();
Value v2=new Value();
v1.i=v2.i=100;
System.out.println(v1.equals(v2));
}
}

//false 缺省行为是比较引用,要么在新类里复写