• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Java中的比较

技术杂谈 勤劳的小蚂蚁 3个月前 (01-25) 64次浏览 已收录 0个评论 扫描二维码


一、==与equals()的区别
首先,我们需要知道==与equals()的区别。
Object中equals()方法的源码如下,从源码中我们可以看出equals()底层调用的就是==,所以在默认情况下,两者比较的都是地址值,不同的是equals()方法可以通过被重写来改变比较规则。

二、基本数据类型及其包装类的比较

我们都知道,byte、short、int、long、boolean、char、double、float这八个是基本数据类型,它们声明的变量存放在栈内存中。而它们对应的包装类型(Byte、Short、Integer、Long、Boolean、Character、Double)定义的变量则存在于堆内存中。对于基本数据类型,它们的比较相对而言较为简单,即判断是否相等用==,比较大小用<、>、<=、>=即可。而对于包装类型,却有些不同。这里的不同主要体现在判断是否相等上。
这里以Long类型为例来说明问题,请看以下代码:
package dailytest;
import org.junit.Test;
/**
* Java中的比较总结
* @author yrr
*/
public class JavaCompareTest {  
   /**
    * Long类型判断是否相等
    */
   @Test
   public void test02() {
       //这里需要注意,使用long定义时,不需要加L或者l,而使用Long时必须加,否则会报错
       //建设都加上,以示区别
       long n3 = 48L;
       System.out.println(“——–使用new对象时,当值在[-127,128]之间时———“);
       Long n7 = new Long(48);
       Long n8 = new Long(48);
       System.out.println(n7 == n8);   //false
       System.out.println(n7 == n3);   //true
       
       System.out.println(“——–直接赋值方式,当值在[-127,128]之间时———“);
       Long n1 = 48L;
       Long n2 = 48L;
       System.out.println(n3 == n1); //true
       System.out.println(n1 == n2); //true
       System.out.println(n1.equals(n2)); //true
       System.out.println(n1.equals(n3)); //true
       System.out.println(n1.intValue() == n2.intValue()); //true
       
       System.out.println(“——–直接赋值方式,当值不在[-127,128]之间时———“);
       Long n4 = 128L;
       Long n5 = 128L;
       long n6 = 128;
       System.out.println(n4 == n5);   //false
       System.out.println(n4 == n6);   //true
       System.out.println(n4.equals(n5));  //true
       System.out.println(n4.equals(n6));  //true
       System.out.println(n4.intValue() == n5.intValue());  //true
       //使用Long.intValue()方法时需要注意验证是否为null,防止出现NullPointException   
   }
}
  针对上面的执行结果,作如下说明:
1. 因为new对象都是在堆里开辟一块空间,所以即便两者的数值相同,对于==来说,比较的是地址值,所以会返回false。
2. 对于基本数据类型的包装类,都重写了equals()方法,会比较数值大小,所以用equals()方法是根据数值大小进行判断的。
3. 对于Integer变量与int变量比较的问题,Integer类型做了自动拆箱,转成了int类型。所以根据数值大小进行判断的。
【注】前三点的解释,对所有包装类型都是适用的,第4点是重点
4. 对于直接赋值方式,值为48的两个Integer变量,用==号判断是true,而当值为128后,却为false。这是因为在底层,对于Integer n1 = 48;这种直接赋值的方式,其实调用了Integer.value()方法。我们可以简单看一下Integer.value()方法的源码, 我们可以看到,这里有个if判断,当输入的i在[-128,127]的范围内时,直接从IntegerCache数组中返回了。所以,对于在这个范围内的数值,返回的都是这个数组对应的地址值,因此用==号判断会返回true。而不在这个范围内的,是new出的对象,因此会返回false。这个结论对于Byte、Short、Integer、Long类型都成立(感兴趣的可以去看下它们对应的value()方法的源码),因为Byte类型的范围就是[-128,127],所以对于Byte类型来说,使用==与equals()没有区别。源码如图示:


【注】需要注意的是,对于大小的比较,即使用>等,会进行自动拆箱的操作,所以对于结果没有什么影响。但是对于包装类,底层都重写了compareTo()方法,建议在比较时,使用这个方法进行比较。同样使用时注意判断null。

三、Java对象的比较
有了上面的介绍之后,对象的比较就比较容易了。原理都是一样的。因为比较简单这里将String类型归在这一类里进行介绍。
1. String类型的比较
需要注意的是,String类型不能直接使用>、<=、>=、<,会报编译异常。
package dailytest;
import org.junit.Test;
public class JavaCompareTest {
   @Test
   public void test03() {
      String s1 = new String(“123”);
      String s2 = new String(“123”);
      System.out.println(s1 == s2);    //false
      System.out.println(s1.equals(s2));
      
      String s3 = “234”;
      String s4 = “234”;
      System.out.println(s3 == s4);    //true
      System.out.println(s3.equals(s4));    //true
      //System.out.println(s1 <= s3); //The operator < is undefined for the argument type(s) java.lang.String, java.lang.String
      System.out.println(s1.compareTo(s3) < 0);   //true
   }
}
  2. 类对象的比较
类对象比较结论也是一样的,但是相对于基本数据类型和String类型,较为复杂一点。根据某一规则,判断两个对象是否相等,需要在被判断类中重写equals()方法,示例代码如下:
而如果要比较两个对象的大小(这也是常会问到的面试题),有两种方式
i) 被比较类实现Comparable接口,并重写compareTo()方法
ii) 自己定义实现了一个Comparator接口的类或者利用内部类,重写compare()方法
两者的区别】:前者定义在被比较类上,而后者定义在被比较类外。通过这种区别,两者的优缺点也很明显,前者简单,但需要对被比较类进行修改,而后者则不需要修改原代码,更加灵活。
第一种方式,示例代码如下:
package dailytest;
import org.junit.Test;
public class JavaCompareTest {
   @Test
   public void test04() {
       Person p1 = new Person(“yrr”,18);
       Person p2 = new Person(“yrr”,18);
       System.out.println(p1 == p2);   //false
       System.out.println(p2.equals(p1));  //true
   }
}
class Person{
   private String name;    
   private Integer age; 
   public Person() {
   }
   public Person(String name, Integer age{
       this.name = name;
       this.age = age;
   }
   public String getName() {
       return name;
   }
   public Integer getAge() {
       return age;
   }
   @Override
   public boolean equals(Object obj{
       Person person = (Person) obj;
       return name.equals(person.getName()) && age.equals(person.getAge());
   }
   
}
第二种方式,示例代码如下:
package dailytest;
import org.junit.Test;
public class JavaCompareTest {
   @Test
   public void test5() {
       Person p1 = new Person(“yrr”,18);
       Person p2 = new Person(“wx”,19);
       System.out.println(p1.compareTo(p2) < 0);
   }
}
class Person implements Comparable<Person>{
   private String name;    
   private Integer age;
   public Person() {
   }
   public Person(String name, Integer age) {
       this.name = name;
       this.age = age;
   }
   public Integer getAge() {
       return age;
   }
   @Override
   public int compareTo(Person o) {
       return this.getAge() – o.getAge();
   } 
}

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Java中的比较
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00