在JAVA 中String 有两种不同的赋值方式 ,"="和new一个新的对象,虽然在输出时显示的内容是一样的,但数据存储的原理是不同的.
String a="ab";
String b="ab";
System.out.println(a==b);//true
三句话的执行时这样的:
当把"ab"赋值给a变量时,因为是用"="直接赋值,此时"ab"作为字面量存在栈中,然后a的引用指向字面量"ab",在编程语言中,字面量是一种表示值的记法.
给 b 赋值ab时,系统会自动查找字面量中是否已经存在 ab,当检测到存在ab时,就会将b的引用指向 ab , 也就是说现在a和b 指向相同的字面量 ,那这时候a = = b作比较时,就会很容易的知道结果为 true;
String a=new String("abc");
String b=new String("abc");
System.out.println(a==b);//false
System.out.println(a);//abc
System.out.println(b);//abc
再看这种赋值方式, a 和 b 都是通过new 出新的对象的方式赋值,对象的产生是动态的,当一个对象产生时,系统会在堆中为每个对象分配不同的内存空间来存放数据,也就是说这里的a 和 b 在堆内存中的地址是不同的.
而 a 和 b都是String类的实例对象,当两个对象通过双等号(“a = = b”)比较时,比较的是两个对象在内存中的地址,如果两个对象内存地址是相同的,得到的结果为true,很显然在上面的例子中,a 和 b的地址是不同的,所以返回结果为 false;
如果要比较a和b 值得大小,需要使用a.equals(b);
在后两句输出语句中,根据常识认为直接输出对象实例名,得到的结果是该实例的内存地址,但是在对字符串输出时,却是输出的内容;其实在其他的普通类中,当打印实例名时,
MyString mString=new MyString();
System.out.println(mString);
打印输出时,系统会自动调用对象的toString()方法,输出的地址: com.neoft.hello.MyString@18a992f;
这是在java源码中就已经写好的,而源码中 String 类的toString()方法中的返回值指定的就是字符串内容.这是String类与其他类的区别.
String a="ab";
String c=new String("ab");
System.out.println(a==c);//false
这三行代码中 a 是指向的字面量,也就是在栈中的值,而c指向的是堆中分配的实例对象空间,因此当 a和c的地址比较时,当然因为地址不同返回false值.
Stringa="ab";
Stringc=new String("ab");
a=c;
System.out.println(a==c);//true
在这四行代码中,因为有 a = c;存在, a不再指向字面量,而是和c一样,将引用指向c的实例在堆中的地址.此时,返回值为true;
String a=new String("ab");
String c=a;
a="ab";
System.out.println(a==c);//false
这四句代码一出,想必能难倒一些刚刚入门的java爱好者.首先前两句, a和b在堆内存中会指向相同的内存地址,此时a 和c的值都是 ab ; 但是 在第三句话或许有许多人不理解,在 a=”ab”;这句话中,对象a 的引用已经指向了栈中的ab 字面量,此时c的值是 堆中的”ab”, a的值是字面量ab ,所以在 a==c 比较时,两个对象指向的内存地址已经发生了变化,返回结果当然为false;