黑马程序员技术交流社区

标题: 我比较两个String总是false,但是它们明明都是"abc" ! [打印本页]

作者: TNTTNT    时间: 2014-3-25 12:16
标题: 我比较两个String总是false,但是它们明明都是"abc" !
小弟求解,谢谢哥们!
作者: TNTTNT    时间: 2014-3-25 12:18
我比较两个String总是false,但是它们明明都是"abc" !
作者: bjfanxc    时间: 2014-3-25 12:48
public static void main(String[] args) {
                String s1 = "abc";
                String s2 = "abc";
                String s3 = new String("abc");
                String s4 = new String("abc");
                System.out.println(s1==s2);
                System.out.println(s3==s4);
        }

如果你比较的是s3和s4那肯定是false因为他们两者比较的是地址值,s1和s2指向的都是同一个“abc”;
作者: TNTTNT    时间: 2014-3-25 12:59
bjfanxc 发表于 2014-3-25 12:48
public static void main(String[] args) {
                String s1 = "abc";
                String s2 = "abc";

比较String一定要使用equals或equalsIgnoreCase方法,不要使用 == !
==比较的是两个引用(变量)是否指向了同一个对象,而不是比较其内容。

刚看完书~~~~~~
作者: 水蓝    时间: 2014-3-25 14:27

  1. public static void main(String[] args) {
  2.                 String s1 = "abc"; //这行代码,只生成一个常量语句,存在于常量池中,并将s1的引用直接指向常量池。
  3.                 String = "abc"; //因为常量池中已经有"abc",所以这行代码没有再申请空间,而是直接将s2 指向常量池中的"abc"。
  4.                 String s3 = new String("abc"); //如果没有以上两行代码,这行代码应该生成两样东西:1、常量池中的字符串常量"abc",2、字符串对象new String("abc"),在堆中。s3的引用指向堆中String对象,而不是字符串常量
  5.                 String s4 = new String("abc"); //同上句,但在堆中是另外新建了String对象,s4的引用指向堆中String对象,而不是字符串常量

  6.                 //至此,常量池中有一个字符串常量"abc",堆中有两个String对象
  7.                 //双等号,只比较对象(常量)的引用地址。
  8.                 //如果要比较值,用equals方法或者equalsIgnoreCase方法
  9.                 System.out.println(s1==s2);
  10.                 System.out.println(s3==s4);
  11.         }
复制代码

作者: luoyilan222    时间: 2014-3-25 16:14
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
注意,我们这里并不用str1.equals(str2);的方式,因为这将比较两个字符串的值是否相等。==号,根据JDK的说明,只有在两个引用都指向了同一个对象时才返回真值。而我们在这里要看的是,str1与str2是否都指向了同一个对象。
结果说明,JVM创建了两个引用str1和str2,但只创建了一个对象,而且两个引用都指向了这个对象。
我们再来更进一步,将以上代码改成:
复制内容到剪贴板代码:
String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
System.out.println(str1 + "," + str2); //bcd, abc
System.out.println(str1==str2); //false
这就是说,赋值的变化导致了类对象引用的变化,str1指向了另外一个新对象!而str2仍旧指向原来的对象。上例中,当我们将str1的值改为"bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。
事实上,String类被设计成为不可改变(immutable)的类。如果你要改变其值,可以,但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。
再修改原来代码:
复制内容到剪贴板代码:
String str1 = "abc";
String str2 = "abc";
str1 = "bcd";
String str3 = str1;
System.out.println(str3); //bcd
String str4 = "bcd";
System.out.println(str1 == str4); //true
str3这个对象的引用直接指向str1所指向的对象(注意,str3并没有创建新对象)。当str1改完其值后,再创建一个String的引用str4,并指向因str1修改值而创建的新的对象。可以发现,这回str4也没有创建新的对象,从而再次实现栈中数据的共享。
我们再接着看以下的代码。
复制内容到剪贴板代码:
String str1 = new String("abc");
String str2 = "abc";
System.out.println(str1==str2); //false 创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str1==str2); //false
创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。
以上两段代码说明,只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。
作者: TNTTNT    时间: 2014-3-26 11:35
luoyilan222 发表于 2014-3-25 16:14
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true

谢谢~~~~~~~




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2