A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李敬卫 中级黑马   /  2013-1-22 07:39  /  2377 人查看  /  12 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class MyClass {
        int x;
        MyClass(int i) {
                x = i;
        }
        public static void main(String args[]) {
                MyClass m1 = new MyClass(100);
                MyClass m2 = new MyClass(100);
                if (m1.equals(m2)) {
                        System.out.println("Both are equal");
                } else {
                        System.out.println("Both are not equal");
                }
               
                String s1=new String("abc");
                String s2=new String("abc");
                System.out.println(s1.equals(s2));
        }
}
我想知道m1.equals(m2)) 为什么为false;而s1.equals(s2))就为true。麻烦解释的时候请详细点

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

12 个回复

正序浏览
     ③构造器形成的差别。对于String和Integer来说,由于他们特有的创建对象的方式。使用构造器和不使用构造器得到一个对象,==方法比较所产生的结果是不同的。 String a = “abc”; String b = "abc"; 此时a==b得到结果为true。String a = new String("abc"); String b = new String("abc");此时a==b得到的结果为false。Integer a = 1; Integer b = 1;此时a==b的结果是true。Integer a = new Integer(1); Integer b = new Integer(1);此时a==b得到的结果为false。

================
楼上哥们的这段话说的非常好!!!为了加强理解与记忆,我再用我自己的话重复一遍。
直接用双引号“”给一个字符串变量赋值与用关键字new来赋相同的值,它们的机理是不同的。
用双引号时,对于相同的字符串在内存中只有一个地址。
用new时,不管字符串是否相同,都将在内存中另外再开辟一个地址空间。
回复 使用道具 举报
详述:

       ①==和equals的实质。

       在JAVA中利用"=="比较变量时,系统使用变量在"栈"中所存的值作为比较的依据。

       基本数据类型在"栈"中存的是其内容值,而对象类型在"栈"中存的是地址,这些地址指向"堆"中的对象。

       java.lang包中的Object类有public boolean equals(Object obj)方法,它比较两个对象是否相等。

       其它对象的equals方法仅当被比较的两个引用指向的对象内容相同时,对象的equals()方法返回true。

       总之,"=="和"!="比较的是地址.也可认为"=="和"!="比较的是对象句柄;而equals()比较的是对象内容.或者说,,"=="和"!="比较的是"栈"中的内容,而equals()比较的是"堆"中的内容.

       ②==操作符。专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相当,只能用==操作符。


      ③构造器形成的差别。对于String和Integer来说,由于他们特有的创建对象的方式。使用构造器和不使用构造器得到一个对象,==方法比较所产生的结果是不同的。 String a = “abc”; String b = "abc"; 此时a==b得到结果为true。String a = new String("abc"); String b = new String("abc");此时a==b得到的结果为false。Integer a = 1; Integer b = 1;此时a==b的结果是true。Integer a = new Integer(1); Integer b = new Integer(1);此时a==b得到的结果为false。

       通过这一点其实我们也能够更加容易理解==对内存的实际操作,实际执行的是近似于基本类型比较。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
equals比较的是栈内存中的地址,==比较的是堆内存的地址。看图。。。。。。

yes.jpg (18.2 KB, 下载次数: 72)

yes.jpg

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报 1 0
李敬卫 来自手机 中级黑马 2013-1-22 16:50:59
10#
[quote]张政 发表于 2013-1-22 09:30
MyClass m1 = new MyClass(100)

哥们,equals比较的是地址啊?你再看看你理解好没
回复 使用道具 举报
李源 初级黑马 2013-1-22 16:25:49
9#
本帖最后由 李源 于 2013-1-22 16:40 编辑

在java中,==与equals的运算是不相同的。
==比较的是内存地址,而equals比较的是内存中所存储的数据。
下边可以试试看,
class MyClass
{
         int x;
         MyClass(int i)
         {
                 x = i;
         }
         public static void main(String args[])
         {
                 MyClass m1 = new MyClass(100);
                 MyClass m2 = new MyClass(100);
                 if (m1.equals(m2))
                  {
                         System.out.println("Both are equal");
                  }
                   else
                  {
                         System.out.println("Both are not equal");
                 }
                 String s1="abc";
                 String s2=new String("abc");
                 String s3=new String("abc");
                 s2=s2.intern();
                 System.out.println(s1.equals(s2));
                 System.out.println(s1.equals(s3));
                 System.out.println(s2.equals(s3));
                 System.out.println(s1==s2);
                 System.out.println(s1==s3);
                 System.out.println(s2==s3);
         }
}
假如没有s2=s2.intern();这句话,那么s2,s3都是new的,分配新的地址,因此,用==进行运算的时候的时候都将是不同的,结果都将是false。而用equals进行运算则得到的是三个abc之间的比较,结果是true。
当假如s2=s2.intern();时,则s2在new的时候将先回到池中寻找是否存在“abc”,这时发现已经存在s1,s2在new的时候将返回s1,在==比较s1和s2时,结果是同一地址,结果变为了true。s3未执行此运算,仍是new的,在与s1、s2的==运算中是不同的,结果是false。
但假如也执行s3=s3.intern();
则实际上s2,s3都返回了s1,无论==或equals运算,同一地址、数据进行比较,结果当然是true。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
李敬卫 来自手机 中级黑马 2013-1-22 16:09:25
8#
2楼3楼,说句不客气的话,你们应该再认真学习下==和equals,我认为你们理解有误。
回复 使用道具 举报
藤倚说的透彻。。api有详细描述
我觉得板凳 理解有点混乱了   所有new一个对象包括字符串,若对象中有字符串常量 此时是直接存值的而不是引用
而对于string s = "abc" 类似这种是需要在常量地址池中开辟空间存放“abc”,若再有引用定义指向相同的字符串,就不会再创建,只是复制一个地址就可以了

另外对于==号的使用 api中有描述是:对于基本数据类型肯定是比较算数值是否相等;而对于引用数据类型比较的是地址值是否相同

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
首先要知道equals方法是从Object类中继承下来的。默认比较内存地址,即是用==来比较。
在String类中,重写了equals方法,按照字符串内容来比较。
在你写的自定义类中MyClass ,你没有重写equals,那就是按照内存地址比较了

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
这个不是我出的题目吗 ??
回复 使用道具 举报
本帖最后由 张政 于 2013-1-22 09:34 编辑

                MyClass m1 = new MyClass(100);
                MyClass m2 = new MyClass(100);
m1.equals(m2) == false 是因为类在new的时候是直接在堆中新开辟的一块空间 所有m1 m2指向的地址就不同
                String s1=new String("abc");
                String s2=new String("abc");
而String就不一样 你s1在堆中new了一块空间存了abc 然后s2再new的时候他会在堆中去找你s2传进来的值 如果堆中有一块空间的值为abc的话他就不会新开辟空间 直接把s1地址给了s2一份 而equals又是比的指向地址 所以为true  这个我记得毕老师视频中讲过 反复蹂躏视频把..
回复 使用道具 举报
额,equals对对象进行比较时比较的是对象的地址,m1跟m2 是两个不同的对象,所以返回false

在String类中,重写了equals方法,比较时如果两个String对象有相同的字符序列,则返回ture
回复 使用道具 举报
m1.equals(m2)) 比的是hashCode的值,两个MyClass都new了对象,所以hashCode是不一样的,所以返回的是false
第二个两个String类型的变量s1和s2都通过new关键字分别创建了一个新的String对象,这个new关键字为创建的每个对象分配一块新的、独立的内存堆。因此当通过"=="来比较它们所引用的是否是同一个对象时,将返回false。而通过equals()方法来比较时,则返回true,因为这两个对象所封装的字符串内容是完全相同的。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马