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才对啊?
}
}

解决方案 »

  1.   

    字符串其实是介于基本类型和对象类型之间的一种类型
    可能是为了提高效率吧,字符串有个常量池,在编译的时候就确定了
    比如上面的代码常量池中会有一个字符串常量,其内容是"my",而2个引用a和b都是指向此常量,因此是相同的
      

  2.   

    String a = new String("my");
     String b = new String("my");这样才是定义了2个不同的地址呢String a="my";
    String b="my";这个就是同一个地址
    是值的比较
      

  3.   

    说了n遍的话,学java有时候买一本书,一心专进去看懂了会比较好的。比如core javaString a="my";
    String b="my";没有通过new 关键字,而new是java中本质上分配内存所必须的,故第一个赋值是查找内存,没找到"my",它会自己new一个,第二次一样的道理,却查到了一摸一样的,就指向它了,但如果还有第三个,却用了new,那就会分配内存初始化一个独立的"my"。还有,String a;a是一个指向String类型对象的引用。所以,我们通常说a是String类型的,起始我们说的是a是一个指向String类型对象的引用。
      

  4.   

    up
    a,b本来都是指向"my",就是同一地址
      

  5.   

    这个结论是100%的吗,有没有可能在String b="my"时没有找到"my",而实际内存中已经存在"my"啦?
      

  6.   

    String a="my";
    String b="my";这个就是同一个地址
    是值的比较
    上面是引用楼上的朋友的回答.想问一下.
    如果像上面那样声明:
    可否这样理解呢:a代表一个内存地址假如是:0xF1,b代表一个内存地址:0xF2
    a==b;您的意思是说:不是0xF1和0xF2比较而是my和my比较;
    那么你有没有想过下面这种情况呢:如下:
    String a="abc";
    String a="bcd";
    a==a此时的比较是内存地址的比较,还是abc=bcd的比较?
      

  7.   

    "故第一个赋值是查找内存,没找到"my",它会自己new一个,第二次一样的道理,却查到了一摸一样的,就指向它了",按照这个理论,用=进行赋值效率是很低的,还不如new来得快?
      

  8.   

    String a="my";
    String b="my";怎么和C++的思想完全不一样了呢?
    变量a    a的内存地址为:0xf1   指向my;
    变量b    b的内存地址为:0xf2   指向my;(;暂时不讨论两个my是否是在同一个地址下)
    想问一下,a==b的比较在java当中到底是自己本身地址的比较,不是指向地址的比较?
      

  9.   

    Code:
    String s= "Hello"; 
     s = s + "world!"; s所指向的对象是否改变了呢?从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中,s原先指向一个String对象,内容是"Hello",然后我们对s进行了+操作,那么s所指向的那个对象是否发生了改变呢?答案是没有。这时,s不指向原来那个对象了,而指向了另一个String对象,内容为"Helloworld!",原来那个对象还存在于内存之中,只是s这个引用变量不再指向它了。 通过上面的说明,我们很容易导出另一个结论,如果经常对字符串进行各种各样的修改,或者说,不可预见的修改,那么使用String来代表字符串的话会引起很大的内存开销。因为String对象建立之后不能再改变,所以对于每一个不同的字符串,都需要一个String对象来表示。这时,应该考虑使用StringBuffer类,它允许修改,而不是每个不同的字符串都要生成一个新的对象。并且,这两种类的对象转换十分容易。 同时,我们还可以知道,如果要使用内容相同的字符串,不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化,把它设置为初始值,应当这样做: Code:
    public class Demo{ 
         private Strings; 
         ... 
        public Demo{ 
           s="Initialvalue"; 
        } 
         ... 
     } 
     而非 
     
     s=new String("Initialvalue"); 
    后者每次都会调用构造器,生成新对象,性能低下且内存开销大,并且没有意义,因为String对象不可改变,所以对于内容相同的字符串,只要一个String对象来表示就可以了。也就说,多次调用上面的构造器创建多个对象,他们的String类型属性s都指向同一个对象。 上面的结论还基于这样一个事实:对于字符串常量,如果内容相同,Java认为它们代表同一个String对象。而用关键字new调用构造器,总是会创建一个新的对象,无论内容是否相同。 至于为什么要把String类设计成不可变类,是它的用途决定的。其实不只String,很多Java标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本,即StringBuffer。
      

  10.   

    只有new了之后才存在对象的具体空间地址
      

  11.   

    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,比较的是它引用的值。
      

  12.   

    我记得以前看过孙鑫老师的书还是教学笔记上说的蛮清楚的,下面有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 缺省行为是比较引用,要么在新类里复写