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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王丽 黑马帝   /  2011-7-27 12:32  /  2809 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一直闹不懂equal(null)和==“”什么时候用啊,有什么区别吗?

6 个回复

倒序浏览
黑马网友  发表于 2011-7-27 14:43:04
沙发
==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是否相等,只能用==操作符。
如果一个变量指向的数据是对象类型的,那么,这时候涉及了两块内存,对象本身占用一块内存(堆内存),变量也占用一块内存,例如Objet obj = new Object();变量obj是一个内存,new Object()是另一个内存,此时,变量obj所对应的内存中存储的数值就是对象占用的那块内存的首地址。对于指向对象类型的变量,如果要比较两个变量是否指向同一个对象,即要看这两个变量所对应的内存中的数值是否相等,这时候就需要用==操作符进行比较。
equals方法是用于比较两个独立对象的内容是否相同,就好比去比较两个人的长相是否相同,它比较的两个对象是独立的。例如,对于下面的代码:
String a=new String("foo");
String b=new String("foo");
两条new语句创建了两个对象,然后用a,b这两个变量分别指向了其中一个对象,这是两个不同的对象,它们的首地址是不同的,即a和b中存储的数值是不相同的,所以,表达式a==b将返回false,而这两个对象中的内容是相同的,所以,表达式a.equals(b)将返回true。
在实际开发中,我们经常要比较传递进行来的字符串内容是否等,例如,String input = …;input.equals(“quit”),许多人稍不注意就使用==进行比较了,这是错误的,随便从网上找几个项目实战的教学视频看看,里面就有大量这样的错误。记住,字符串的比较基本上都是使用equals方法。
如果一个类没有自己定义equals方法,那么它将继承Object类的equals方法,Object类的equals方法的实现代码如下:
boolean equals(Object o){
return this==o;
}
这说明,如果一个类没有自己定义equals方法,它默认的equals方法(从Object 类继承的)就是使用==操作符,也是在比较两个变量指向的对象是否是同一对象,这时候使用equals和使用==会得到同样的结果,如果比较的是两个独立的对象则总返回false。如果你编写的类希望能够比较该类创建的两个实例对象的内容是否相同,那么你必须覆盖equals方法,由你自己写代码来决定在什么情况即可认为两个对象的内容是相同的。
回复 使用道具 举报
黑马网友  发表于 2011-7-27 14:58:51
藤椅
在对字符串的相等判断,==判断的是地址是否相同,equal()判断的是字符值是否相同。大多数时候==跟equal()的结果都是相同的。这是因为String对象是不变模式的,如果你不是明确地new一个String对象,Java对于String对象的保存默认的是会把新生成的String 对象放到一个缓冲区,然后每次判断缓冲区中是否已经有了这个对象,如果有了,那么后建立的同样字符值的String对象也会指向最初建立是该字符值对象的地址。也就是说字符值相同的时候,大多数情况下地质也是相同的。==与equal()效果是相同的。但是当对象是str = new String(“abc”)生成的而不是直接str = “abc”这样赋值生成,或者经过了一些字符串连接处理,或者通过StringBuffer等对象生成,都会在内存中开辟新的地址的,这个时候==和 equal()结果是不同的。
回复 使用道具 举报
使用==来判断两个变量是否相等,如果2个变量是基本类型的变量,且都是数值型(不一定要求数据类型严格相同),则只要两个变量的值相等,使用==判断就返回true
但对于两个引用类型的变量,必须他们指向一个对象,==才会返回true,==不可比较类型上没有父子关系的两个对象
如下:[code=java]package cn.itcast.zhanjc;


/**
* Description:
*
*/
public class TestEqual
{
        public static void main(String[] args)
        {
                int it = 65;
                float fl = 65.0f;
                //将输出true
                System.out.println("65和65.0f是否相等?" + (it == fl));
                char ch = 'A';
                //将输出true
                System.out.println("65和'A'是否相等?" + (it == ch));
                String str1 = new String("hello");
                String str2 = new String("hello");
                //将输出false
                System.out.println("str1和str2是否相等?" + (str1 == str2));
                //将输出true
                System.out.println("str1是否equals str2?" + (str1.equals(str2)));

        }
}[/code]所以很多时候,程序判断两个引用变量是否相等的时候,是希望一种类似于值相等的判断规则,并不要求这两个引用是不是指向一个对象,例如上面程序中的两个字符串对象,需要他们引用字符串对象包含的字符串序列即可相等,这就需要equals。

注:Object类提供的equals方法和==方法符合没有区别,如下为Object中equals方法,可见他和==无区别[code=java]    public boolean equals(Object obj) {
        return (this == obj);
    }[/code]所以我们在使用这个方法采用自定义的相等标准,重写这个方法

我们在重写equals方法的时候,会判断需要比较的对象和调用这个方法的对象是否相等时时在这两个对象是同一个类的实例的基础上
但是由于instanceof运算份特殊性,当前面对象是后面类的实例或者他子类的实例都将返回true,所以我们最好用两个类的字节码来判断是否为同一个类的实例,并且当两个对象是同一个对象的时候直接返回true,[code=java]package cn.itcast.zhanjc;
//定义一个Person类
class Person
{
        private String name;
        private String idStr;
        public Person(){}
        public Person(String name , String idStr)
        {
                this.name = name;
                this.idStr = idStr;
        }
        //下面省略name和idStr的setter和getter方法。
        .........

        //重写equals方法,提供自定义的相等标准
        public boolean equals(Object obj)
        {
                //待比较的两个对象是同一个对象,直接返回true
                if(this == obj)
                {
                        return true;
                }
                //只有当obj是Person对象
                if (obj != null && obj.getClass() == Person.class)
                {
                        Person personObj = (Person)obj;
                        //并且当前对象的idStr与obj对象的idStr相等才可判断两个对象相等
                        if (this.getIdStr().equals(personObj.getIdStr()))
                        {
                                return true;
                        }
                }
                return false;
        }

}[/code]
[ 本帖最后由 詹季春 于 2011-07-28  00:09 编辑 ]
回复 使用道具 举报
==是针对基本数据类型的,因为基本数据类型是放在栈区里面的,栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们定义了两个变量 int a=5;int b=5; 编译器会先处理a=5,他先在栈中找有没有面值5的地址,如果没有给他开辟一个新的空间,并把5放入该空间块中,当编译器处理b=5时,也是在栈中找有没有面值为5的地址,因为前面已经开辟了这样的空间所以b不用开辟新的空间直接指向面值为5的空间地址。所以说我们平常说用的==指的是否地址值相同。 包装类数据是在推中动态的分配空间的,是通过new一个实例来实现的,因为里面的值是被包装起来的,所以每new一个实例就会产生一个新的地址空间不管里面的值如何,这时用==方法只能比较两个变量的地址根本没办法比较两个包装类对象里面的的值,而equals是比较两个变量(包括包装类变量)里面的面值是否相同而不是比较地址是否相同。String  Integer  Double等是一种特殊的包装类,不需要下new()方法编译器自动的给他创建了一个对象。可用[/font[code=java]String s="dd";
         boolean b4=s.getClass().isInstance(s);
          System.out.println(b4 == true ? "s是个对象 " : "s不是对象");[/code]
验证s是不是对象。
回复 使用道具 举报
黑马网友  发表于 2011-7-27 17:44:06
地板

回复 楼主 的帖子

String s1="xxx";
String s2="yyy";
==是比较s1与s2是否相等 他比较的是对象的指向是否相等
equals是比较 xxx 与yyy 是否相等   它比较的是对象的内容
回复 使用道具 举报
黑马网友  发表于 2011-7-27 18:08:17
7#
这个问题要从java表示数据的方式说起,java有两类数据类型:基本数据类型(int,char等)和复合数据类型(就是类)。对于基本数据类型,java会在内存中开辟数个字节存储其实际内容,比如int占用4个字节,char占用一个字节;而对于复合数据类型,由于通常其数据较多所以占用内存也很多,java的做法是为实际数据开辟一块内存A,另外开辟一处内存B 存储实际数据存储区A的地址(即引用),使用时只是通过B找到A,再对A进行相应操作。String是复合数据类型。String sName="Jone";该语句会开辟一处内存A1存储"Jone",然后再开辟一块内存B1即sName,用来存放"Jone"内存区A1的首地址。同样语句String sUser="Jone";也如此分配内存,内存A2存储"Jone",内存B2即sUser存放A2的首地址。注意:虽然A1和A2存储的内容一样但是它们的首地址是不一样的。
在java中,==就是直接比较两块内存的内容是否相等,表达式sName==sUser的实质是比较内存A1和A2的内容是否相等,即比较内存B1和B2的首地址是否相等,结果当然是false。因此比较两个String对象的内容是否相等用==是不准确的,所以java的String类提供了equals()方法,该方法就是通过对象的引用找到实际的内容区进行比较。具体请参考jdk文档对equals()方法的说明。
以上是我给人的见解,不对之处请大家指正。谢谢
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马