Java的equals和==问题

Java中equals和==的区别,是十分经典的问题。本人有次面试时,就被问了这个问题。在此深入研究下。
第一原则:
equals和==都是比较变量(varivable)才可以比较。类、方法、接口等非变量是不能比较的。 
以下代码,编译器是不能通过的。
eg1:
class A{
     void fun(){
     }
}

class B{
     void fun(){
     }
}

interface C{
}

interface D{
}

public class test2 {
     public static void main(String[] args){
           A a = new A();
           B b = new B();
           System. out.println(A.equals( B));
           System. out.println(C.equals( D));
     }
}

第二原则:
基础数据类型是可以直接用==比较的。

在第一原则的情况下,Java的变量分为基本数据类型和引用型,两者比较是不同的。
首先熟悉下Java的变量存储机制。
1、基本数据类型( 包括数值型,字符型和布尔型 )在创建时, 在栈上给其划分一块内存,将数值直接存储在栈(stack)上。
  
2、引用数据类型在被创建时,首先要在栈上给其引用(句柄)分配一块内存,而对象的具体信息都存储在堆内存上,然后由栈上面的引用指向堆中对象的地址。
          在eg1中,A a = new A(),简单的一句话,其实执行了如下的步骤:
               step1:在stack区分配了一块区域,存放a;
               step2:在heap区新建A的一个对象;
               step3:将A对象在堆内存中的地址,赋值给栈中的a,通过句柄a可以找到堆中对象的具体信息。
当我们使用==比较时,比较的是在stack内容中存储的内容,所以基础类型是可以直接用==比较的,那么引用型的呢?
第三原则:
     引用型变量的比较, 要具体情况具体分析。
     结合具体情况是指结合什么东西的具体情况呢,当然是指JDK文档中的不同对象的equals方法了。
     情况一:
eg2:
     class A{
      void fun(){
     }
   }

   public class test2 {
      public static void main(String[] args){
           A a1 = new A();
           A a2 = new A();
           System. out.println(a1.equals(a2));
     }
   }   

打印结果是false,这是怎么回事?当我们新建A对象时,继承的是java.lang.Object,并且没有重写equals方法。而Object类中的equals方法是用来比较“地址”的,所以等于false。
     
     情况二:
eg3:
     public class test2 {
      public static void main(String[] args){
           String str = new String( "helloworld");
           String str2 = new String( "helloworld");
           System. out.println(str.equals(str2));
     }
   }

打印结果是true,这是怎么回事?在JDK中String的equals方法已经被重写,比较就是内容,所以等于true。

情况三:
eg4:
     public class test2 {
      public static void main(String[] args){
           StringBuffer str = new StringBuffer( "helloworld");
           StringBuffer str2 = new StringBuffer( "helloworld");
           System. out.println(str.equals(str2));
     }
   }

 打印结果是false,这是因为StringBuffer并没有重写equals方法,还是比较的地址。
 读到这里,大家也许明白了,equals千万不能死记硬背,要根据JDK的文档来查看相应对象的比较方法才行。而我们自己定义的类,如果想用equals的比较的话,就需要重写了。
 eg5:
     class A{
      private String age;

      public String getAge() {
            return age;
     }

      public void setAge(String age) {
            this. age = age;
     }

      public boolean equals(A a) {
            return this. age.equals(a. age);
     }
     
     }

     public class test2 {
          public static void main(String[] args){
           A a1 = new A();
           a1.setAge( "12");
           A a2 = new A();
           a2.setAge( "12");
           System. out.println(a1.equals(a2));
          }
     }  

打印结果是true! 
PS: 还有一种很特殊的情况,既可以使用equals又可以使用==,这就涉及到Java的装箱拆箱了(详见笔者的另一篇文章:点击打开链接)。
     分析:
     在C语言中,数组的定义方法有两种:
          char  a[] = "leirenbaobao"          
          char  *p =  "leirenbaobao"
     第一种是用数组定义,第二种是用指针指向字符串常量区的一个字符串,而字符串常量区有个特性:当我定义了char  *p =  "leirenbaobao"时,再定义个char *q = "leirenbaobao",这时候字符常量区不再新建另一个"leirenbaobao",而是将两个指针同时指向一个第一个"leirenbaobao",想必这样也是为了程序执行的效率吧。

     而在java中,也是这尿性,java的字符串常量区,有时也被称为字符串常量池。
eg6:
     public class test2 {
      public static void main(String[] args){
           String str = "leirenbaobao";
           String str2 = "leirenbaobao";
           System. out.println(str.equals(str2));
           System. out.println(str==str2);
     }
   }

结果返回两个true。

     Ctrl+Z presents!


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值