2019Java面試彙總(一)

  1. String,StringBuffer,StringBuilder的區別是什麼?String爲何是不可變的?

可變性java

​ String類中使用的是final關鍵字修飾字符數組保存字符串,private final char value[],因此String對象是不可變的。git

​ StringBuffer和StringBuilder都繼承AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組來保存字符串 char[] value,可是沒有用final關鍵字修飾,因此兩種對象是可變的。github

線程安全性面試

​ String中的對象是不可變的,所以也能夠理解成線程安全的。數組

​ AbstractStringBuilder 是 StringBuilder 與 StringBuffer 的公共父類,定義了一些字符串的基本操做,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。StringBuilder 並無對方法進行加同步鎖,因此是非線程安全的。安全

​ (引伸一道題:i++是線程安全的嗎?=============>線程不安全)多線程

性能app

​ 每次對String類型進行改變的時候,都會生成一個新的String對象,而後將指針指向新的String對象,這個過程當中會從新開闢內存空間,對內存空間極大的浪費。ide

​ StringBuffer 每次都會對 StringBuffer 對象自己進行操做,而不是生成新的對象並改變對象引用。相同狀況下使用 StringBuilder 相比使用 StringBuffer 僅能得到 10%~15% 左右的性能提高,但卻要冒多線程不安全的風險。函數

​ 所以:因爲 StringBuilder 相較於 StringBuffer 有速度優點,因此多數狀況下建議使用 StringBuilder 類。然而在應用程序要求線程安全的狀況下,則必須使用 StringBuffer 類。

總結
1.少許數據:適用String
2.單線程操做字符串緩衝區下操做大量數據: 適用StringBuilder
3.多線程操做字符串緩衝區下操做大量數據: 適用StringBuffer

  1. 構建器Constructor是否可被override?

​ java中,父類的私有屬性和構造方法都不能被繼承,因此Constructor也就不能被重寫,可是能夠重載,全部能夠看到一個類中有多個構建函數的狀況。

  1. 重寫和重載的區別

​ 重寫:重寫是子類對父類的容許訪問的方法的實現過程進行從新編寫,發生在子類中,方法名、參數列表必須相同,返回值範圍小於等於父類,拋出的異常範圍小於等於父類,訪問修飾符範圍大於等於父類。另外,若是父類方法訪問修飾符爲 private 則子類就不能重寫該方法。也就是說方法提供的行爲改變,而方法的外貌並無改變。

​ 重載:同一個類中,方法名相同,參數類型不一樣,個數不一樣,順序不一樣,方法返回值和訪問修飾符不一樣。eg:構建函數。

  1. Java面向對象的三大特性(繼承,封裝,多態)

​ 封裝:封裝把一個對象的屬性私有化,同時提供一些能夠被外界訪問的屬性的方法,(get,set)。

​ 繼承:繼承是使用已存在的類的定義做爲基礎創建新類的技術,新類的定義能夠增長新的數據或新的功能,也能夠用父類的功能,但不能選擇性地繼承父類。經過使用繼承咱們可以很是方便地複用之前的代碼。

​ 多態:多態指的是同一個方法調用,因爲對象不一樣可能會有不一樣的行爲。

  1. 自動裝箱與拆箱(JDK1.5引入)

​ 裝箱:將基本類型用它們對應的引用類型包裝起來;

​ 拆箱:將包裝類型轉換爲基本數據類型;

​ 基本類型與引用類型:

​ 基礎數據類型:它們存儲的都是數據量比較小的數據,只須要1個或者少許幾個字節就能夠了,所以,這些數據類型的變量的二進制就直接保存着他們的值。
​ 引用數據類型:它主要用來指向某個對象,對象保存的數據通常都比較大。

基本數據類型 引用數據類型
byte Byte
short Short
int Integer
long Long
float Float
double Double
char Character
boolean Boolean

  1. 靜態方法內調用一個非靜態成員爲何是非法的?

​ 普通的方法調用都是經過」對象名.方法名「來調用,即須要一個對象,然而靜態方法能夠不經過對象進行調用,所以不能調用其餘非靜態變量,也不能訪問非靜態變量的成員。

  1. 對象的相等與指向他們的引用相等,二者有什麼不一樣?

​ 對象的相等,比的是內存中存放的內容是否相等。而引用相等,比較的是他們指向的內存地址是否相等。

  1. == 與 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("true");
        if (37 == 37.0) { // true
            System.out.println("true");
        }
    }
}

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

  1. 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 first java》第二版)。這樣咱們就大大減小了 equals 的次數,相應就大大提升了執行速度。

​ 經過咱們能夠看出:hashCode() 的做用就是獲取哈希碼,也稱爲散列碼;它其實是返回一個int整數。這個哈希碼的做用是肯定該對象在哈希表中的索引位置。hashCode()在散列表中才有用,在其它狀況下沒用。在散列表中hashCode() 的做用是獲取對象的散列碼,進而肯定該對象在散列表中的位置。

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

若是兩個對象相等,則hashcode必定也是相同的
兩個對象相等,對兩個對象分別調用equals方法都返回true
兩個對象有相同的hashcode值,它們也不必定是相等的
所以,equals 方法被覆蓋過,則 hashCode 方法也必須被覆蓋
hashCode() 的默認行爲是對堆上的對象產生獨特值。若是沒有重寫 hashCode(),則該 class 的兩個對象不管如何都不會相等(即便這兩個對象指向相同的數據)
10.線程,進程,程序的基本概念及關係
​ 線程與進程類似,但線程是一個比進程更小的執行單位。一個進程在其執行的過程當中能夠產生多個線程。與進程不一樣的是同類的多個線程共享同一塊內存空間和一組系統資源,因此係統在產生一個線程,或是在各個線程之間做切換工做時,負擔要比進程小得多,也正由於如此,線程也被稱爲輕量級進程。

​ 程序是含有指令和數據的文件,被存儲在磁盤或其餘的數據存儲設備中,也就是說程序是靜態的代碼。

​ 進程是程序的一次執行過程,是系統運行程序的基本單位,所以進程是動態的。系統運行一個程序便是一個進程從建立,運行到消亡的過程。簡單來講,一個進程就是一個執行中的程序,它在計算機中一個指令接着一個指令地執行着,同時,每一個進程還佔有某些系統資源如CPU時間,內存空間,文件,輸入輸出設備的使用權等等。換句話說,當程序在執行時,將會被操做系統載入內存中。 線程是進程劃分紅的更小的運行單位。線程和進程最大的不一樣在於基本上各進程是獨立的,而各線程則不必定,由於同一進程中的線程極有可能會相互影響。從另外一角度來講,進程屬於操做系統的範疇,主要是同一段時間內,能夠同時執行一個以上的程序,而線程則是在同一程序內幾乎同時執行一個以上的程序段。

參考:https://github.com/Snailclimb...

相關文章
相關標籤/搜索