最最最多見的Java基礎知識面試題總結

這裏會分享一些出現頻率極其極其高的面試題,初定周更一篇,何時更完何時中止。html

Github地址:https://github.com/Snailclimb/Java-Guide/blob/master/面試必備/最最最多見的Java面試題總結/第一週(2018-8-7).mdjava

一 Java中的值傳遞和引用傳遞(很是重要)

首先要明確的是:「對象傳遞(數組、類、接口)是引用傳遞,原始類型數據(整型、浮點型、字符型、布爾型)傳遞是值傳遞。」git

那麼什麼是值傳遞和應用傳遞呢?

值傳遞是指對象被值傳遞,意味着傳遞了對象的一個副本,即便副本被改變,也不會影響源對象。(由於值傳遞的時候,其實是將實參的值複製一份給形參。)github

引用傳遞是指對象被引用傳遞,意味着傳遞的並非實際的對象,而是對象的引用。所以,外部對引用對象的改變會反映到全部的對象上。(由於引用傳遞的時候,其實是將實參的地址值複製一份給形參。)面試

有時候面試官不是單純問你「Java中是值傳遞仍是引用傳遞」是什麼啊,騷年?而是給出一個例子,而後讓你寫出答案,這種也常見在筆試題目中!因此,很是重要了,請看下面的例子:編程

值傳遞和應用傳遞實例

1. 值傳遞

public static void main(String[] args) {
    int num1 = 10;
    int num2 = 20;

    swap(num1, num2);

    System.out.println("num1 = " + num1);
    System.out.println("num2 = " + num2);
}

public static void swap(int a, int b) {
    int temp = a;
    a = b;
    b = temp;

    System.out.println("a = " + a);
    System.out.println("b = " + b);
}

結果:後端

a = 20
b = 10
num1 = 10
num2 = 20

解析:數組

在swap方法中,a、b的值進行交換,並不會影響到num一、num2。由於,a、b中的值,只是從num一、num2的複製過來的。
也就是說,a、b至關於num一、num2的副本,副本的內容不管怎麼修改,都不會影響到原件自己。微信

2. 引用傳遞

public static void main(String[] args) {
    int[] arr = {1,2,3,4,5};

    change(arr);

    System.out.println(arr[0]);
}

public static void change(int[] array) {
//將數組的第一個元素變爲0
    array[0] = 0;
}

結果:app

1
0

解析:

不管是主函數,仍是change方法,操做的都是同一個地址值對應的數組。 。所以,外部對引用對象的改變會反映到全部的對象上。

一些特殊的例子

1. StringBuffer類型傳遞

// 測試引用傳遞:StringBuffer
    @org.junit.Test
    public void method1() {
        StringBuffer str = new StringBuffer("公衆號:Java面試通關手冊");
        System.out.println(str);
        change1(str);
        System.out.println(str);
    }

    public static void change1(StringBuffer str) {
        str = new StringBuffer("abc");//輸出:「公衆號:Java面試通關手冊」
        //str.append("歡迎你們關注");//輸出:公衆號:Java面試通關手冊歡迎你們關注
        //str.insert(3, "(編程)");//輸出:公衆號(編程):Java面試通關手冊
        
    }

結果:

公衆號:Java面試通關手冊
公衆號:Java面試通關手冊

解析:

不少要這個時候要問了:StringBuffer建立的明明也是對象,那爲何輸出結果依然是原來的值呢?

由於在change1方法內部咱們是新建了一個StringBuffer對象,因此str指向了另一個地址,相應的操做也一樣是指向另外的地址的。

那麼,若是將change1方法改爲以下圖所示,想必你們應該知道輸出什麼了,若是你還不知道,那可能就是我講的有問題了,我反思(開個玩笑,上面程序中已經給出答案):

public static void change1(StringBuffer str) {

        str.append("歡迎你們關注");
        str.insert(3, "(編程)");
        
    }

2. String類型傳遞

// 測試引用傳遞:Sring
    @org.junit.Test
    public void method2() {
        String str = new String("公衆號:Java面試通關手冊");
        System.out.println(str);
        change2(str);
        System.out.println(str);
    }

    public static void change2(String str) {
        // str="abc"; //輸出:公衆號:Java面試通關手冊
        str = new String("abc"); //輸出:公衆號:Java面試通關手冊
    }

結果:

公衆號:Java面試通關手冊
公衆號:Java面試通關手冊

能夠看到不管是執行str="abc;"仍是str = new String("abc");str的輸出的值都不變。
按照咱們上面講「StringBuffer類型傳遞」的時候說的,str="abc;"應該會讓str的輸出的值都不變。爲何呢?由於String在建立以後是不可變的。

3. 一道相似的題目

下面的程序輸出是什麼?

public class Demo {
    public static void main(String[] args) {
        Person p = new Person("張三");

        change(p);

        System.out.println(p.name);
    }

    public static void change(Person p) {
        Person person = new Person("李四");
        p = person;
    }
}

class Person {
    String name;

    public Person(String name) {
        this.name = name;
    }
}

很明顯仍然會輸出張三。由於change方法中從新建立了一個Person對象。

那麼,若是把 change方法改成下圖所示,輸出結果又是什麼呢?

public static void change(Person p) {
        p.name="李四";
    }

答案我就不說了,我以爲你們若是認真看完上面的內容以後應該很很清楚了。

二 ==與equals(重要)

== : 它的做用是判斷兩個對象的地址是否是相等。即,判斷兩個對象是否是同一個對象。(基本數據類型==比較的是值,引用數據類型==比較的是內存地址)

equals() : 它的做用也是判斷兩個對象是否相等。但它通常有兩種使用狀況:

  • 狀況1:類沒有覆蓋equals()方法。則經過equals()比較該類的兩個對象時,等價於經過「==」比較這兩個對象。
  • 狀況2:類覆蓋了equals()方法。通常,咱們都覆蓋equals()方法來兩個對象的內容相等;若它們的內容相等,則返回true(即,認爲這兩個對象相等)。

舉個例子:

public class test1 {
    public static void main(String[] args) {
        String a = new String("ab"); // a 爲一個引用
        String b = new String("ab"); // b爲另外一個引用,對象的內容同樣
        String aa = "ab"; // 放在常量池中
        String bb = "ab"; // 從常量池中查找
        if (aa == bb) // true
            System.out.println("aa==bb");
        if (a == b) // false,非同一對象
            System.out.println("a==b");
        if (a.equals(b)) // true
            System.out.println("aEQb");
        if (42 == 42.0) { // true
            System.out.println("true");
        }
    }
}

說明:

  • String中的equals方法是被重寫過的,由於object的equals方法是比較的對象的內存地址,而String的equals方法比較的是對象的值。
  • 當建立String類型的對象時,虛擬機會在常量池中查找有沒有已經存在的值和要建立的值相同的對象,若是有就把它賦給當前引用。若是沒有就在常量池中從新建立一個String對象。

三 hashCode與equals(重要)

面試官可能會問你:「你重寫過 hashcode 和 equals 麼,爲何重寫equals時必須重寫hashCode方法?」

hashCode()介紹

hashCode() 的做用是獲取哈希碼,也稱爲散列碼;它其實是返回一個int整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。hashCode() 定義在JDK的Object.java中,這就意味着Java中的任何類都包含有hashCode() 函數。

散列表存儲的是鍵值對(key-value),它的特色是:能根據「鍵」快速的檢索出對應的「值」。這其中就利用到了散列碼!(能夠快速找到所須要的對象)

爲何要有hashCode

咱們以「HashSet如何檢查重複」爲例子來講明爲何要有hashCode:

當你把對象加入HashSet時,HashSet會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其餘已經加入的對象的hashcode值做比較,若是沒有相符的hashcode,HashSet會假設對象沒有重複出現。可是若是發現有相同hashcode值的對象,這時會調用equals()方法來檢查hashcode相等的對象是否真的相同。若是二者相同,HashSet就不會讓其加入操做成功。若是不一樣的話,就會從新散列到其餘位置。(摘自個人Java啓蒙書《Head fist java》第二版)。這樣咱們就大大減小了equals的次數,相應就大大提升了執行速度。

hashCode()與equals()的相關規定

  1. 若是兩個對象相等,則hashcode必定也是相同的
  2. 兩個對象相等,對兩個對象分別調用equals方法都返回true
  3. 兩個對象有相同的hashcode值,它們也不必定是相等的
  4. 所以,equals方法被覆蓋過,則hashCode方法也必須被覆蓋
  5. hashCode()的默認行爲是對堆上的對象產生獨特值。若是沒有重寫hashCode(),則該class的兩個對象不管如何都不會相等(即便這兩個對象指向相同的數據)

寫在最後

推薦一個本身的開源的後端文檔

Java-Guide: Java面試通關手冊(Java學習指南)Java Interview Customs Manual (Java Study Guide)。star:1.4k。

👉Github地址:https://github.com/Snailclimb/Java-Guide

👊文檔定位:一個專門爲Java後端工程師準備的開源文檔,相信不論你是Java新手仍是已經成爲一名Java工程師都能從這份文檔中收穫到一些東西。

參考:

http://www.javashuo.com/article/p-weorerwi-dx.html

http://www.javashuo.com/article/p-cpkvtyxf-es.html

http://www.javashuo.com/article/p-cpkvtyxf-es.html

https://www.cnblogs.com/Eason-S/p/5524837.html

若是想要獲取更多個人原創文章以及優質學習資源,歡迎關注個人微信公衆號:" Java面試通關手冊" 。無套路,但願能與您共同進步,互相學習。

相關文章
相關標籤/搜索