欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java比較問題詳細(xì)分析

 更新時(shí)間:2017年12月22日 11:31:49   作者:DemonFS  
本篇文章主要給大家講解了Java中比較問題的相關(guān)知識(shí),一起參考學(xué)習(xí)下吧。

Java中的比較問題是一個(gè)很基礎(chǔ)又很容易混淆的問題。今天就幾個(gè)容易出錯(cuò)的點(diǎn)作一個(gè)比較詳細(xì)的歸納與整理,希望對(duì)大家的學(xué)習(xí)與面試有幫助。

一、==與equals()的區(qū)別

首先,我們需要知道==與equals()的區(qū)別,==號(hào)比較的一直是地址值,對(duì)于基本數(shù)據(jù)類型來說,==比較實(shí)際上就是變量數(shù)值是否相等,而對(duì)于引用數(shù)據(jù)類型,比較的則是地址值。這里特別需要注意的是String類型,很容易想當(dāng)然的使用==,很容易出錯(cuò)。equals()方法是Object類里的方法,我們知道Java中一切類都會(huì)默認(rèn)繼承Object類,所以類對(duì)象都會(huì)有equals()方法。Object類中equals()方法如下圖所示:

由源碼可以看出,Object類里的equals()方法底層也是用的==,所以它比較的其實(shí)也是地址值。所以如果想用equals()方法去作其他比較,我們需要重寫equals()方法。

二、基本數(shù)據(jù)類型及其包裝類

我們都知道,byte、short、int、long、boolean、char、double、float這八個(gè)是基本數(shù)據(jù)類型,它們聲明的變量存放在棧內(nèi)存中。而它們對(duì)應(yīng)的包裝類型(Byte、Short、Integer、Long、Boolean、Character、Double)定義的變量則存在于堆內(nèi)存中。對(duì)于基本數(shù)據(jù)類型,它們的比較相對(duì)而言較為簡單,即判斷是否相等用==,比較大小用<、>、<=、>=即可。而對(duì)于包裝類型,卻有些不同。

首先對(duì)于判斷是否相等,看如下代碼的執(zhí)行結(jié)果:

package dailytest;
import org.junit.Test;
/**
 * Java中的比較總結(jié)
 * @author yrr
 */
public class JavaCompareTest {
  /**
   * Integer類型判斷是否相等
   */
  @Test
  public void test01() {
    int n3 = 48;
    System.out.println("--------使用new對(duì)象時(shí),當(dāng)值在[-127,128]之間時(shí)---------");
    Integer n7 = new Integer(48);
    Integer n8 = new Integer(48);
    System.out.println(n7 == n8);  //false
    System.out.println(n7 == n3);  //true
    System.out.println("--------直接賦值方式,當(dāng)值在[-128,127]之間時(shí)---------");
    Integer n1 = 48;
    Integer n2 = 48;
    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("--------直接賦值方式,當(dāng)值不在[-127,128]之間時(shí)---------");
    Integer n4 = 128;
    Integer n5 = 128;
    int 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
    //使用Integer.intValue()方法時(shí)需要注意驗(yàn)證是否為null,防止出現(xiàn)NullPointException
  }
  /**
   * Long類型判斷是否相等
   */
  @Test
  public void test02() {
    //這里需要注意,使用long定義時(shí),不需要加L或者l,而使用Long時(shí)必須加,否則會(huì)報(bào)錯(cuò)
    //建設(shè)都加上,以示區(qū)別
    long n3 = 48L;
    System.out.println("--------使用new對(duì)象時(shí),當(dāng)值在[-127,128]之間時(shí)---------");
    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("--------直接賦值方式,當(dāng)值在[-127,128]之間時(shí)---------");
    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("--------直接賦值方式,當(dāng)值不在[-127,128]之間時(shí)---------");
    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()方法時(shí)需要注意驗(yàn)證是否為null,防止出現(xiàn)NullPointException  
  }
}

針對(duì)上面的執(zhí)行結(jié)果,作如下說明:

首先,對(duì)于new方法來聲明一個(gè)Integer或者Long對(duì)象,因?yàn)閚ew對(duì)象都是在堆里開辟一塊空間,所以即便兩者的數(shù)值相同,但對(duì)于==來說,比較的是地址值,所以會(huì)返回false。 對(duì)于基本數(shù)據(jù)類型的包裝類,都重寫了equals()方法,會(huì)比較數(shù)值大小,所以用equals()方法是可以根據(jù)數(shù)值大小進(jìn)行判斷的。 對(duì)于Integer變量與int變量比較的問題,會(huì)發(fā)現(xiàn)也是基于數(shù)值大小得出來的比較值,這是因?yàn)樵诒容^時(shí),Integer類型做了自動(dòng)拆箱,轉(zhuǎn)成了int類型。 前三點(diǎn)的解釋,對(duì)所有包裝類型都是適用的 對(duì)于直接賦值方式,值為48的兩個(gè)Integer變量,用==號(hào)判斷是true,而當(dāng)值為128后,卻為false。這是因?yàn)樵诘讓?,?duì)于Integer n1 = 48;這種直接賦值的方式,其實(shí)調(diào)用了Integer.value()方法。我們可以簡單看一下Integer.value()方法的源碼,如下圖所示:

我們可以看到,這里有個(gè)if判斷,當(dāng)輸入的i在[-128,127]的范圍內(nèi)時(shí),直接從IntegerCache數(shù)組中返回了。所以,對(duì)于在這個(gè)范圍內(nèi)的數(shù)值,返回的都是這個(gè)數(shù)組對(duì)應(yīng)的地址值,因此用==號(hào)判斷會(huì)返回true。而不在這個(gè)范圍內(nèi)的,是new出的對(duì)象,因此會(huì)返回false。這個(gè)結(jié)論對(duì)于Byte、Short、Integer、Long類型都成立(感興趣的可以去看下它們對(duì)應(yīng)的value()方法的源碼),因?yàn)锽yte類型的范圍就是[-128,127],所以對(duì)于Byte類型來說,使用==與equals()沒有區(qū)別。 

而對(duì)于大小比較,使用>、<、<=、>=是沒有問題的,它們會(huì)進(jìn)行自動(dòng)拆箱。但是我們通常建議使用以下兩種方式來進(jìn)行大小比較:

調(diào)用xxxValue()方法轉(zhuǎn)成基本數(shù)據(jù)類型進(jìn)行比較 使用compareTo()方法進(jìn)行比較,在包裝類中,都重寫了compareTo()方法。查看compareTo()源碼,可以看出,其實(shí)它底層使用的也是通過自動(dòng)拆箱轉(zhuǎn)成了對(duì)應(yīng)的基本數(shù)據(jù)類型再進(jìn)行比較的。

二、Java對(duì)象的比較

有了上面的介紹之后,對(duì)象的比較就比較容易了。原理都是一樣的。

1. String類型的比較

需要注意的是,String類型不能直接使用>、<=、>=、<,會(huì)報(bào)編譯異常。

package dailytest;
import org.junit.Test;
/**
 * Java中的比較總結(jié)
 * @author yrr
 */
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. 類對(duì)象的比較

類對(duì)象比較結(jié)論也是一樣的,但是相對(duì)于基本數(shù)據(jù)類型和String類型,較為復(fù)雜一點(diǎn)。

根據(jù)某一規(guī)則,判斷兩個(gè)對(duì)象是否相等,需要在被判斷類中重寫equals()方法,示例代碼如下:

package dailytest;
import org.junit.Test;
/**
 * Java中的比較總結(jié)
 * @author yrr
 */
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());
  }
  
}

而如果要比較兩個(gè)對(duì)象的大?。ㄟ@也是常會(huì)問到的面試題),有兩種方式:

被比較類實(shí)現(xiàn)Comparable接口,并重寫compareTo()方法 自己定義實(shí)現(xiàn)了一個(gè)Comparator接口的類或者利用內(nèi)部類,重寫compare()方法 兩者的區(qū)別:前者定義在被比較類上,而后者定義在被比較類外。通過這種區(qū)別,兩者的優(yōu)缺點(diǎn)也很明顯,前者簡單,但需要對(duì)被比較類進(jìn)行修改,而后者則不需要修改原代碼,更加靈活。

第一種方式,示例代碼如下:

package dailytest;
import org.junit.Test;
/**
 * Java中的比較總結(jié)
 * @author yrr
 */
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();
  }  
}

第二種方式,示例代碼如下:

package comparator;
import java.util.Arrays;
import java.util.Comparator;
public class MyComparator {
  public static void main(String[] args) {
    User[] users = new User[] { new User("u1001", 25), 
        new User("u1002", 20), new User("u1003", 21) };
    Arrays.sort(users, new Comparator<User>() {

      @Override
      public int compare(User o1, User o2) {
        return o1.getAge() - o2.getAge();
      }
    });
    for (int i = 0; i < users.length; i++) { 
      User user = users[i]; 
      System.out.println(user.getId() + " " + user.getAge()); 
    } 
  }
}
class User { 
  private String id; 
  private int age; 
 
  public User(String id, int age) { 
    this.id = id; 
    this.age = age; 
  } 
  public int getAge() { 
    return age; 
  } 
  public void setAge(int age) { 
    this.age = age; 
  } 
  public String getId() { 
    return id; 
  } 
  public void setId(String id) { 
    this.id = id; 
  } 
}

以上就是本次給大家講的Java中比較問題的相關(guān)內(nèi)容,大家還有其他問題可以在下方留言區(qū)討論,感謝你的支持。

相關(guān)文章

  • Java并發(fā)內(nèi)存模型詳情

    Java并發(fā)內(nèi)存模型詳情

    這篇文章主要介紹了Java并發(fā)內(nèi)存模型,Java是一門支持多線程執(zhí)行的語言,要編寫正確的并發(fā)程序,了解Java內(nèi)存模型是重要前提。而了解硬件內(nèi)存模型有助于理解程序的執(zhí)行,下面文章就來看看詳細(xì)內(nèi)容吧
    2021-10-10
  • 詳解Java中clone的寫法

    詳解Java中clone的寫法

    這篇文章主要介紹了Java中clone的寫法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-07-07
  • Java并發(fā)編程之Semaphore的使用簡介

    Java并發(fā)編程之Semaphore的使用簡介

    這篇文章主要介紹了Java并發(fā)編程之Semaphore的使用簡介,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-04-04
  • Spring Boot 單元測試JUnit的實(shí)踐

    Spring Boot 單元測試JUnit的實(shí)踐

    JUnit是一款優(yōu)秀的開源Java單元測試框架,也是目前使用率最高最流行的測試框架,這篇文章主要介紹了Spring Boot 單元測試JUnit的實(shí)踐,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Spring-Task定時(shí)任務(wù)的使用介紹

    Spring-Task定時(shí)任務(wù)的使用介紹

    目前springboot應(yīng)用廣泛,因此對(duì)于spring-task直接基于springboot框架介紹,不涉及xml配置。本文直接介紹spring-task的使用方法,需要的可以參考一下
    2022-11-11
  • java基于Socket做一個(gè)簡單下載器

    java基于Socket做一個(gè)簡單下載器

    這篇文章主要為大家詳細(xì)介紹了java如何基于Socket制作一個(gè)簡單下載器,感興趣的小伙伴們可以參考一下
    2016-08-08
  • ManyToMany單向、雙向:@JoinTable的使用

    ManyToMany單向、雙向:@JoinTable的使用

    這篇文章主要介紹了ManyToMany單向、雙向:@JoinTable的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java實(shí)戰(zhàn)房屋租賃網(wǎng)的實(shí)現(xiàn)流程

    Java實(shí)戰(zhàn)房屋租賃網(wǎng)的實(shí)現(xiàn)流程

    讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+jsp+mysql+maven實(shí)現(xiàn)一個(gè)房屋租賃網(wǎng)站,大家可以在過程中查缺補(bǔ)漏,提升水平
    2021-11-11
  • 使用maven打包生成doc文檔和打包源碼

    使用maven打包生成doc文檔和打包源碼

    這篇文章主要介紹了使用maven打包生成doc文檔和打包源碼的實(shí)現(xiàn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java多線程文件下載器的實(shí)現(xiàn)

    java多線程文件下載器的實(shí)現(xiàn)

    本文主要介紹了java多線程文件下載器的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11

最新評(píng)論