Java經典面試題解析(1-80題)

前言

前幾天,在茫茫的互聯網海洋中尋尋覓覓,我收藏了800道Java基礎經典面試題,有小夥伴私聊我要答案。因此感受沒有答案的面試題是沒有靈魂的,因而今天先整理基礎篇的前80道答案出來~html

全部的Java面試題已經上傳github,答案也上傳了一部分~java

github.com/whx123/Java…git

公衆號:撿田螺的小男孩程序員

Java 基礎

1. equals與==的區別

==

  • 若是是基本類型,==表示判斷它們值是否相等;
  • 若是是引用對象,==表示判斷兩個對象指向的內存地址是否相同。

equalsgithub

  • 若是是字符串,表示判斷字符串內容是否相同;
  • 若是是object對象的方法,比較的也是引用的內存地址值;
  • 若是本身的類重寫equals方法,能夠自定義兩個對象是否相等。

2. final, finally, finalize 的區別

  • final 用於修飾屬性,方法和類, 分別表示屬性不能被從新賦值, 方法不可被覆蓋, 類不可被繼承.
  • finally 是異常處理語句結構的一部分,通常以ty-catch-finally出現,finally代碼塊表示老是被執行.
  • finalize 是Object類的一個方法,該方法通常由垃圾回收器來調用,當咱們調用System.gc() 方法的時候,由垃圾回收器調用finalize()方法,回收垃圾,JVM並不保證此方法總被調用.

3. 重載和重寫的區別

  • 重寫必須繼承,重載不用。
  • 重載表示同一個類中能夠有多個名稱相同的方法,但這些方法的參數列表各不相同(即參數個數或類型不一樣)
  • 重寫表示子類中的方法與父類中的某個方法的名稱和參數徹底相同啦,經過子類實例對象調用這個方法時,將調用子類中的定義方法,這至關於把父類中定義的那個徹底相同的方法給覆蓋了,這是面向對象編程的多態性的一種表現。
  • 重寫的方法修飾符大於等於父類的方法,即訪問權限只能比父類的更大,不能更小,而重載和修飾符無關。
  • 重寫覆蓋的方法中,只能比父類拋出更少的異常,或者是拋出父類拋出的異常的子異常,由於不能坑爹啊哈哈~

4. 兩個對象的hashCode()相同,則 equals()是否也必定爲 true?

兩個對象equals相等,則它們的hashcode必須相等,若是兩個對象的hashCode()相同,則equals()不必定爲true。面試

hashCode 的常規協定:sql

  • 在 Java 應用程序執行期間,在對同一對象屢次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另外一次執行,該整數無需保持一致。
  • 兩個對象的equals()相等,那麼對這兩個對象中的每一個對象調用 hashCode 方法都必須生成相同的整數結果。
  • 兩個對象的equals()不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不要求必定生成不一樣的整數結果。可是,爲不相等的對象生成不一樣整數結果能夠提升哈希表的性能。

5. 抽象類和接口有什麼區別

  • 抽象類要被子類繼承,接口要被子類實現。
  • 抽象類能夠有構造方法,接口中不能有構造方法。
  • 抽象類中能夠有普通成員變量,接口中沒有普通成員變量,它的變量只能是公共的靜態的常量
  • 一個類能夠實現多個接口,可是隻能繼承一個父類,這個父類能夠是抽象類。
  • 接口只能作方法聲明,抽象類中能夠做方法聲明,也能夠作方法實現。
  • 抽象級別(從高到低):接口>抽象類>實現類。
  • 抽象類主要是用來抽象類別,接口主要是用來抽象方法功能。
  • 抽象類的關鍵字是abstract,接口的關鍵字是interface

6. BIO、NIO、AIO 有什麼區別?

這個答案來自互聯網哈,我的以爲是最好理解的~編程

  • BIO:線程發起 IO 請求,無論內核是否準備好 IO 操做,從發起請求起,線程一直阻塞,直到操做完成。
  • NIO:線程發起 IO 請求,當即返回;內核在作好 IO 操做的準備以後,經過調用註冊的回調函數通知線程作 IO 操做,線程開始阻塞,直到操做完成。
  • AIO:線程發起 IO 請求,當即返回;內存作好 IO 操做的準備以後,作 IO 操做,直到操做完成或者失敗,經過調用註冊的回調函數通知線程作 IO 操做完成或者失敗。

BIO 是一個鏈接一個線程。,NIO 是一個請求一個線程。,AIO 是一個有效請求一個線程。設計模式

  • BIO:同步並阻塞,服務器實現模式爲一個鏈接一個線程,即客戶端有鏈接請求時服務器端就須要啓動一個線程進行處理,若是這個鏈接不作任何事情會形成沒必要要的線程開銷,固然能夠經過線程池機制改善。
  • NIO:同步非阻塞,服務器實現模式爲一個請求一個線程,即客戶端發送的鏈接請求都會註冊到多路複用器上,多路複用器輪詢到鏈接有I/O請求時才啓動一個線程進行處理。
  • AIO:異步非阻塞,服務器實現模式爲一個有效請求一個線程,客戶端的 IO 請求都是由 OS 先完成了再通知服務器應用去啓動線程進行處理。

7. String,Stringbuffer,StringBuilder的區別

String:數組

  • String類是一個不可變的類,一旦建立就不能夠修改。
  • String是final類,不能被繼承
  • String實現了equals()方法和hashCode()方法

StringBuffer:

  • 繼承自AbstractStringBuilder,是可變類。
  • StringBuffer是線程安全的
  • 能夠經過append方法動態構造數據。

StringBuilder:

  • 繼承自AbstractStringBuilder,是可變類。
  • StringBuilder是非線性安全的。
  • 執行效率比StringBuffer高。

8. JAVA中的幾種基本數據類型是什麼,各自佔用多少字節呢

基本類型 位數 字節
int 32 4
short 16 2
long 64 8
byte 8 1
char 16 2
float 32 4
double 64 8
boolean

對於boolean,官方文檔未明肯定義,它依賴於 JVM 廠商的具體實現。邏輯上理解是佔用 1位,可是實際中會考慮計算機高效存儲因素

感興趣的小夥伴,能夠去看官網

9. Comparator與Comparable有什麼區別?

在牛客網看到這道題的答案,以爲寫的最好~

連接:www.nowcoder.com/questionTer… 來源:牛客網

  • Comparable & Comparator 都是用來實現集合中元素的比較、排序的,只是 Comparable 是在集合內部定義的方法實現的排序,Comparator 是在集合外部實現的排序,因此,如想實現排序,就須要在集合外定義 Comparator 接口的方法或在集合內實現 Comparable 接口的方法。
  • Comparator位於包java.util下,而Comparable位於包 java.lang下。
  • Comparable 是一個對象自己就已經支持自比較所須要實現的接口(如 String、Integer 本身就能夠完成比較大小操做,已經實現了Comparable接口) 自定義的類要在加入list容器中後可以排序,能夠實現Comparable接口,在用Collections類的sort方法排序時,若是不指定Comparator,那麼就以天然順序排序, 這裏的天然順序就是實現Comparable接口設定的排序方式。
  • 而 Comparator 是一個專用的比較器,當這個對象不支持自比較或者自比較函數不能知足你的要求時,你能夠寫一個比較器來完成兩個對象之間大小的比較。
  • 能夠說一個是自已完成比較,一個是外部程序實現比較的差異而已。 用 Comparator 是策略模式(strategy design pattern),就是不改變對象自身,而用一個策略對象(strategy object)來改變它的行爲。 好比:你想對整數採用絕對值大小來排序,Integer 是不符合要求的,你不須要去修改 Integer 類(實際上你也不能這麼作)去改變它的排序行爲,只要使用一個實現了 Comparator 接口的對象來實現控制它的排序就好了。

10. String類能被繼承嗎,爲何。

首先,String是一個final修飾的類,final修飾的類不能夠被繼承。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
複製代碼

String類爲何不能被繼承呢?

有兩個緣由:

  • 效率性,String 類做爲最經常使用的類之一,禁止被繼承和重寫,能夠提升效率。
  • 安全性,String 類中有不少調用底層的本地方法,調用了操做系統的 API,若是方法能夠重寫,可能被植入惡意代碼,破壞程序。

11. 說說Java中多態的實現原理

  • 多態機制包括靜態多態(編譯時多態)和動態多態(運行時多態)
  • 靜態多態好比說重載,動態多態通常指在運行時才能肯定調用哪一個方法。
  • 咱們一般所說的多態通常指運行時多態,也就是編譯時不肯定究竟調用哪一個具體方法,一直等到運行時才能肯定。
  • 多態實現方式:子類繼承父類(extends)和類實現接口(implements)
  • 多態核心之處就在於對父類方法的改寫或對接口方法的實現,以取得在運行時不一樣的執行效果。
  • Java 裏對象方法的調用是依靠類信息裏的方法表實現的,對象方法引用調用和接口方法引用調用的大體思想是同樣的。當調用對象的某個方法時,JVM查找該對象類的方法表以肯定該方法的直接引用地址,有了地址後才真正調用該方法。

舉個例子吧,假設有個Fruit父類,一個taste味道方法,兩個子類Apple和Pear,以下:

abstract class Fruit {
    abstract String taste() ;
}

class Apple extends Fruit {
    @Override
    String taste() {
        return "酸酸的";
    }
}

class Pear extends Fruit {
    @Override
    String taste() {
        return "甜甜的";
    }
}
public class Test {
    public static void main(String[] args) {
        Fruit f = new Apple();
        System.out.println(f.taste());
    }
}
複製代碼

程序運行,當調用對象Fruit f的方法taste時,JVM查找Fruit對象類的方法表以肯定taste方法的直接引用地址,到底來自Apple仍是Pear,肯定後才真正調用對應子類的taste方法,

12. Java泛型和類型擦除

這個面試題,能夠看我這篇文章哈~

Java程序員必備基礎:泛型解析

13. int和Integer 有什麼區別,還有Integer緩存的實現

這裏考察3個知識點吧:

  • int 是基本數據類型,interger 是 int 的封裝類
  • int 默認值爲 0 ,而interger 默認值爲 null, Interger使用須要判空處理
  • Integer的緩存機制:爲了節省內存和提升性能,Integer類在內部經過使用相同的對象引用實現緩存和重用,Integer類默認在-128 ~ 127 之間,能夠經過 -XX:AutoBoxCacheMax進行修改,且這種機制僅在自動裝箱的時候有用,在使用構造器建立Integer對象時無用。

看個Integer的緩存的例子,加深一下印象哈:

Integer a = 10;
Integer b = 10;

Integer c = 129;
Integer d = 129;
System.out.println(a == b);
System.out.println(c == d);
輸出結果:
true
false
複製代碼

14. 說說反射的用途及實現原理,Java獲取反射的三種方法

這道面試題,看我這篇文章哈:談談Java反射:從入門到實踐,再到原理

Java獲取反射的三種方法

  • 第一種,使用 Class.forName 靜態方法。
  • 第二種,使用類的.class 方法
  • 第三種,使用實例對象的 getClass() 方法。

15. 面向對象的特徵

面向對象的三大特徵:

  • 封裝
  • 繼承
  • 多態

16. &和&&的區別

  • 按位與, a&b 表示把a和b都轉換成二進制數,再進行與的運算;
  • &和&&都是邏輯運算符號,&&又叫短路運算符
  • 邏輯與,a&& b ,a&b 都表示當且僅當兩個操做數均爲 true時,其結果才爲 true,不然爲false。
  • 邏輯與跟短路與的差異是很是巨大的,雖然兩者都要求運算符左右兩端的布爾值都是true,整個表達式的值纔是true。可是,&&之因此稱爲短路運算,是由於若是&&左邊的表達式的值是false,右邊的表達式會被直接短路掉,不會進行運算。

17. Java中IO流分爲幾種?

  • Java中的流分爲兩種:一種是字節流,另外一種是字符流。
  • IO流分別由四個抽象類來表示(兩輸入兩輸出):InputStream,OutputStream,Reader,Writer。

18. 講講類的實例化順序,好比父類靜態數據,構造函數,子類靜態數據,構造函數。

直接看個例子吧:

public class Parent {
    {
        System.out.println("父類非靜態代碼塊");
    }
    static {
        System.out.println("父類靜態塊");
    }
    public Parent() {
        System.out.println("父類構造器");
    }
}
public class Son extends Parent {
    public Son() {
        System.out.println("子類構造器");
    }
    static {
        System.out.println("子類靜態代碼塊");
    }
    {
        System.out.println("子類非靜態代碼塊");
    }
}
public class Test {
    public static void main(String[] args) {
        Son son = new Son();
    }
}
複製代碼

運行結果:

父類靜態塊
子類靜態代碼塊
父類非靜態代碼塊
父類構造器
子類非靜態代碼塊
子類構造器
複製代碼

因此,類實例化順序爲: 父類靜態代碼塊/靜態域->子類靜態代碼塊/靜態域 -> 父類非靜態代碼塊 -> 父類構造器 -> 子類非靜態代碼塊 -> 子類構造器

19. Java建立對象有幾種方式

Java建立對象有5種方式

  • 用new語句建立對象。
  • 使用反射,使用Class.newInstance()建立對象/調用類對象的構造方法——Constructor
  • 調用對象的clone()方法。
  • 運用反序列化手段,調用java.io.ObjectInputStream對象的readObject()方法.
  • 使用Unsafe

20. 如何將GB2312編碼的字符串轉換爲ISO-8859-1編碼的字符串呢?

public class Test {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "撿田螺的小男孩";
        String strIso = new String(str.getBytes("GB2312"), "ISO-8859-1");
        System.out.println(strIso);
    }
}
複製代碼

21. 守護線程是什麼?用什麼方法實現守護線程

  • 守護線程是運行在後臺的一種特殊進程。
  • 它獨立於控制終端而且週期性地執行某種任務或等待處理某些發生的事件。
  • 在 Java 中垃圾回收線程就是特殊的守護線程。

22. notify()和 notifyAll()有什麼區別?

  • notify是喚醒一個處於該對象wait的線程,而notifyAll是喚醒全部處於該對象wait的線程。
  • 可是喚醒不等於就能執行了,須要獲得鎖對象纔能有權利繼續執行,而鎖只有一把,因此多個線程被喚醒時須要爭取該鎖。

23. Java語言是如何處理異常的,關鍵字throws、throw、try、catch、finally怎麼使用?

這道面試題,能夠看我這篇文章哈:Java程序員必備:異常的十個關鍵知識點

24. 談談Java的異常層次結構

從前從前,有位老人,他的名字叫Throwable,他生了兩個兒子,大兒子叫Error,二兒子叫Exception

Error

表示編譯時或者系統錯誤,如虛擬機相關的錯誤,OutOfMemoryError等,error是沒法處理的。

Exception

代碼異常,Java程序員關心的基類型一般是Exception。它能被程序自己能夠處理,這也是它跟Error的區別。

它能夠分爲RuntimeException(運行時異常)和CheckedException(可檢查的異常)。

常見的RuntimeException異常:

- NullPointerException 空指針異常
- ArithmeticException 出現異常的運算條件時,拋出此異常
- IndexOutOfBoundsException 數組索引越界異常
- ClassNotFoundException 找不到類異常
- IllegalArgumentException(非法參數異常)
複製代碼

常見的 Checked Exception 異常:

- IOException (操做輸入流和輸出流時可能出現的異常)
- ClassCastException(類型轉換異常類)
複製代碼
  • Checked Exception就是編譯器要求你必須處置的異常。
  • 與之相反的是,Unchecked Exceptions,它指編譯器不要求強制處置的異常,它包括Error和RuntimeException 以及他們的子類。

25. 靜態內部類與非靜態內部類有什麼區別

這道面試題,能夠看我這篇文章哈:Java程序員必備基礎:內部類解析

  • 靜態內部類能夠有靜態成員(方法,屬性),而非靜態內部類則不能有靜態成員(方法,屬性)。
  • 靜態內部類只可以訪問外部類的靜態成員和靜態方法,而非靜態內部類則能夠訪問外部類的全部成員(方法,屬性)。
  • 實例化靜態內部類與非靜態內部類的方式不一樣
  • 調用內部靜態類的方法或靜態變量,能夠經過類名直接調用

26. String s與new String與有什麼區別

String str ="whx";
String newStr =new String ("whx");
複製代碼

String str ="whx"

先在常量池中查找有沒有"whx" 這個對象,若是有,就讓str指向那個"whx".若是沒有,在常量池中新建一個「whx」對象,並讓str指向在常量池中新建的對象"whx"。

String newStr =new String ("whx");

是在堆中創建的對象"whx" ,在棧中建立堆中"whx" 對象的內存地址。

如圖所示:

網上這篇文章講的挺好的: String和New String()的區別

27. 反射中,Class.forName和ClassLoader的區別

Class.forName和ClassLoader均可以對類進行加載。它們區別在哪裏呢? ClassLoader負責加載 Java 類的字節代碼到 Java 虛擬機中。Class.forName實際上是調用了ClassLoader,以下:

這裏面,forName0的第二個參數爲true,表示對加載的類進行初始化化。其實還能夠調用 Class<?> forName(String name, boolean initialize, ClassLoader loader)方法實現同樣的功能,它的源碼以下:

因此,Class.forName和ClassLoader的區別,就是在類加載的時候,class.forName有參數控制是否對類進行初始化。

28. JDK動態代理與cglib實現的區別

  • java動態代理是利用反射機制生成一個實現代理接口的匿名類,在調用具體方法前調用InvokeHandler來處理。
  • cglib動態代理是利用asm開源包,對代理對象類的class文件加載進來,經過修改其字節碼生成子類來處理。
  • JDK動態代理只能對實現了接口的類生成代理,而不能針對類
  • cglib是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法。由於是繼承,因此該類或方法最好不要聲明成final

網上這篇文章寫得不錯,描述Java動態代理的幾種實現方式,分別說出相應的優缺點

29. error和exception的區別,CheckedException,RuntimeException的區別。

Error: 表示編譯時或者系統錯誤,如虛擬機相關的錯誤,OutOfMemoryError等,error是沒法處理的。

Exception: 代碼異常,Java程序員關心的基類型一般是Exception。它能被程序自己能夠處理,這也是它跟Error的區別。

它能夠分爲RuntimeException(運行時異常)和CheckedException(可檢查的異常)。 常見的RuntimeException異常:

- NullPointerException 空指針異常
- ArithmeticException 出現異常的運算條件時,拋出此異常
- IndexOutOfBoundsException 數組索引越界異常
- ClassNotFoundException 找不到類異常
- IllegalArgumentException(非法參數異常)
複製代碼

常見的 Checked Exception 異常:

- IOException (操做輸入流和輸出流時可能出現的異常)
- ClassCastException(類型轉換異常類)
複製代碼

有興趣能夠看我以前寫得這篇文章: Java程序員必備:異常的十個關鍵知識點

30. 深拷貝和淺拷貝區別

淺拷貝

複製了對象的引用地址,兩個對象指向同一個內存地址,因此修改其中任意的值,另外一個值都會隨之變化。

深拷貝

將對象及值複製過來,兩個對象修改其中任意的值另外一個值不會改變

31. JDK 和 JRE 有什麼區別?

  • JDK:Java Development Kit 的簡稱,Java 開發工具包,提供了 Java 的開發環境和運行環境。
  • JRE:Java Runtime Environment 的簡稱,Java 運行環境,爲 Java 的運行提供了所需環境。

32. String 類的經常使用方法都有那些呢?

  • indexOf():返回指定字符的索引。
  • charAt():返回指定索引處的字符。
  • replace():字符串替換。
  • trim():去除字符串兩端空白。
  • split():分割字符串,返回一個分割後的字符串數組。
  • getBytes():返回字符串的 byte 類型數組。
  • length():返回字符串長度。
  • toLowerCase():將字符串轉成小寫字母。
  • toUpperCase():將字符串轉成大寫字符。
  • substring():截取字符串。
  • equals():字符串比較。

33. 談談自定義註解的場景及實現

  • 以前我這邊有這麼一個業務場景,用Redis控制接口調用頻率,有使用過自定義註解。
  • 經過 AOP(動態代理機制)給方法添加切面,經過反射來獲取方法包含的註解,若是包含自定義關鍵字註解,就經過Redis進行校驗攔截請求。

有關於註解,建議你們看一下java編程思想的註解篇章哈~

34. 說說你熟悉的設計模式有哪些?

設計模式分爲三大類:

  • 建立型模式:工廠方法模式、抽象工廠模式、單例模式、建造者模式、原型模式(5種)
  • 結構型模式:適配器模式、裝飾者模式、代理模式、外觀模式、橋接模式、組合模式、享元模式。(7種)
  • 行爲型模式:策略模式、模板方法模式、觀察者模式、迭代子模式、責任鏈模式、命令模式、備忘錄模式、狀態模式、訪問者模式、中介者模式、解釋器模式。(11種)

最好平時積累一下,單例模式(7種實現方式),工廠模式,模板方法設計模式,策略模式,裝飾者模式、代理模式這幾種怎麼寫吧~

我的以爲,能夠看看Hollis大神相關設計模式的文章哈,寫得特別好!設計模式(二)——單例模式

35. 抽象工廠和工廠方法模式的區別?

能夠看一下這篇文章介紹: 抽象工廠模式-與-工廠方法模式區別

36. 什麼是值傳遞和引用傳遞?

  • 值傳遞是對基本型變量而言的,傳遞的是該變量的一個副本,改變副本不影響原變量.
  • 引用傳遞通常是對於對象型變量而言的,傳遞的是該對象地址的一個副本, 並非原對象自己 。 因此對引用對象進行操做會同時改變原對象.

37. 能夠在static環境中訪問非static變量嗎?

static變量在Java中是屬於類的,它在全部的實例中的值是同樣的。當類被Java虛擬機載入的時候,會對static變量進行初始化。由於靜態的成員屬於類,隨着類的加載而加載到靜態方法區內存,當類加載時,此時不必定有實例建立,沒有實例,就不能夠訪問非靜態的成員。類的加載先於實例的建立,所以靜態環境中,不能夠訪問非靜態!

38. Java支持多繼承麼,爲何?

不支持多繼承,緣由:

  • 安全性的考慮,若是子類繼承的多個父類裏面有相同的方法或者屬性,子類將不知道具體要繼承哪一個。
  • Java提供了接口和內部類以達到實現多繼承功能,彌補單繼承的缺陷。

39. 用最有效率的方法計算2乘以8?

2 << 3
複製代碼
  • 將一個數左移n位,就至關於這個數乘以了2的n次方。
  • 那麼,一個數乘以8只要將其左移3位便可。
  • 而cpu直接支持位移運算,且效率最高。

40. 構造器是否可被重寫?

構造器是不能被繼承的,由於每一個類的類名都不相同,而構造器名稱與類名相同,因此談不上繼承。 又因爲構造器不能被繼承,因此相應的就不能被重寫了。

41. char型變量中能不能存貯一箇中文漢字,爲何?

在Java中,char類型佔2個字節,並且Java默認採用Unicode編碼,一個Unicode碼是16位,因此一個Unicode碼佔兩個字節,Java中不管漢子仍是英文字母都是用Unicode編碼來表示的。因此,在Java中,char類型變量能夠存儲一箇中文漢字。

char ch = '啦';
System.out.println("char:" + ch);
複製代碼

42. 如何實現對象克隆?

  • 實現 Cloneable 接口,重寫 clone() 方法。
  • Object 的 clone() 方法是淺拷貝,即若是類中屬性有自定義引用類型,只拷貝引用,不拷貝引用指向的對象。
  • 對象的屬性的Class 也實現 Cloneable 接口,在克隆對象時也手動克隆屬性,完成深拷貝
  • 結合序列化(JDK java.io.Serializable 接口、JSON格式、XML格式等),完成深拷貝

43. object中定義了哪些方法?

  • getClass(); 獲取類結構信息
  • hashCode() 獲取哈希碼
  • equals(Object) 默認比較對象的地址值是否相等,子類能夠重寫比較規則
  • clone() 用於對象克隆
  • toString() 把對象轉變成字符串
  • notify() 多線程中喚醒功能
  • notifyAll() 多線程中喚醒全部等待線程的功能
  • wait() 讓持有對象鎖的線程進入等待
  • wait(long timeout) 讓持有對象鎖的線程進入等待,設置超時毫秒數時間
  • wait(long timeout, int nanos) 讓持有對象鎖的線程進入等待,設置超時納秒數時間
  • finalize() 垃圾回收前執行的方法

44. hashCode的做用是什麼?

  • hashCode的存在主要是用於查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲結構中肯定對象的存儲地址的;
  • 若是兩個對象相同,就是適用於equals(java.lang.Object) 方法,那麼這兩個對象的hashCode必定要相同;
  • 若是對象的equals方法被重寫,那麼對象的hashCode也儘可能重寫,而且產生hashCode使用的對象,必定要和equals方法中使用的一致,不然就會違反上面提到的第2點;
  • 兩個對象的hashCode相同,並不必定表示兩個對象就相同,也就是不必定適用於equals(java.lang.Object) 方法,只可以說明這兩個對象在散列存儲結構中.

這篇文章講得挺詳細的:Java中hashCode的做用

45. for-each與常規for循環的效率對比

關於這個問題,《Effective Java》給咱們作的解答:

for-each可以讓代碼更加清晰,而且減小了出錯的機會。 下面的慣用代碼適用於集合與數組類型:

for (Element e : elements) {
     doSomething(e); 
}
複製代碼

使用for-each循環與常規的for循環相比,並不存在性能損失,即便對數組進行迭代也是如此。實際上,在有些場合下它還能帶來微小的性能提高,由於它只計算一次數組索引的上限。

46. 寫出幾種單例模式實現,懶漢模式和餓漢模式區別

7種:

  • 第一種(懶漢,線程不安全)
  • 第二種(懶漢,線程安全)
  • 第三種(餓漢)
  • 第四種(餓漢,變種)
  • 第五種(靜態內部類)
  • 第六種(枚舉):
  • 第七種(雙重校驗鎖)

能夠看這篇文章:單例模式的七種寫法

47. 請列出 5 個運行時異常。

- NullPointerException 空指針異常
- ArithmeticException 出現異常的運算條件時,拋出此異常
- IndexOutOfBoundsException 數組索引越界異常
- ClassNotFoundException 找不到類異常
- IllegalArgumentException(非法參數異常)
複製代碼

48. 2個不相等的對象有可能具備相同的 hashcode嗎?

有可能哈~

hashCode 的常規協定:

  • 在 Java 應用程序執行期間,在對同一對象屢次調用 hashCode 方法時,必須一致地返回相同的整數,前提是將對象進行 equals 比較時所用的信息沒有被修改。從某一應用程序的一次執行到同一應用程序的另外一次執行,該整數無需保持一致。
  • 兩個對象的equals()相等,那麼對這兩個對象中的每一個對象調用 hashCode 方法都必須生成相同的整數結果。
  • 兩個對象的equals()不相等,那麼對這兩個對象中的任一對象上調用 hashCode 方法不要求必定生成不一樣的整數結果。可是,爲不相等的對象生成不一樣整數結果能夠提升哈希表的性能。

49. 訪問修飾符public,private,protected,以及default的區別?

50. 談談final在java中的做用?

  • final 修飾的類叫最終類,該類不能被繼承。
  • final 修飾的方法不能被重寫。
  • final 修飾的變量叫常量,常量必須初始化,初始化以後值就不能被修改。

51. java中的Math.round(-1.5) 等於多少呢?

JDK 中的 java.lang.Math 類:

  • round() :返回四捨五入,負 .5 小數返回較大整數,如 -1.5 返回 -1。
  • ceil() :返回小數所在兩整數間的較大值,如 -1.5 返回 -1.0。
  • floor() :返回小數所在兩整數間的較小值,如 -1.5 返回 -2.0。

52. String屬於基礎的數據類型嗎?

String 不屬於基礎類型,基礎類型有 8 種:byte、boolean、char、short、int、float、long、double,而 String 屬於對象。

53. 如何將字符串反轉呢?

  • 使用 StringBuilder 或 StringBuffer 的 reverse 方法,本質都調用了它們的父類 AbstractStringBuilder 的 reverse 方法實現。(JDK1.8)
  • 使用chatAt函數,倒過來輸出;

54. 描述動態代理的幾種實現方式,它們分別有什麼優缺點

  • JDK動態代理
  • CGLIB動態代理
  • JDK原聲動態代理時java原聲支持的、不須要任何外部依賴、可是它只能基於接口進行代理
  • CGLIB經過繼承的方式進行代理、不管目標對象沒有沒實現接口均可以代理,可是沒法處理final的狀況

55. 在本身的代碼中,若是建立一個java.lang.String類,這個類是否能夠被類加載器加載?爲何。

不能夠。由於JDK處於安全性的考慮,基於雙親委派模型,優先加載JDK的String類,若是java.lang.String已經加載,便不會再次被加載。

56. 談談你對java.lang.Object對象中hashCode和equals方法的理解。在什麼場景下須要從新實現這兩個方法。

  • 在咱們的業務系統中判斷對象時有時候須要的不是一種嚴格意義上的相等,而是一種業務上的對象相等。在這種狀況下,原生的equals方法就不能知足咱們的需求了,因此這個時候咱們須要重寫equals方法,來知足咱們的業務系統上的需求。
  • 那麼爲何在重寫equals方法的時候須要重寫hashCode方法呢? 若是隻重寫了equals方法而沒有重寫hashCode方法的話,則會違反約定的第二條:相等的對象必須具備相等的散列碼.因此hashCode和equals方法都須要重寫

能夠看網上這篇文章哈:java爲何要重寫hashCode和equals方法

57. 在jdk1.5中,引入了泛型,泛型的存在是用來解決什麼問題。

Java 泛型(generics)是 JDK 5 中引入的一個新特性,其本質是參數化類型,解決不肯定具體對象類型的問題。
複製代碼

這個面試題,能夠看我這篇文章哈~Java程序員必備基礎:泛型解析

58. 什麼是序列化,怎麼序列化,反序列呢?

  • 序列化:把Java對象轉換爲字節序列的過程
  • 反序列:把字節序列恢復爲Java對象的過程

能夠看我這篇文章哈~ Java程序員必備:序列化全方位解析

59. java8的新特性。

  • Lambda 表達式:Lambda容許把函數做爲一個方法的參數
  • Stream API :新添加的Stream API(java.util.stream) 把真正的函數式編程風格引入到Java中
  • 方法引用:方法引用提供了很是有用的語法,能夠直接引用已有Java類或對象(實例)的方法或構造器。
  • 默認方法:默認方法就是一個在接口裏面有了一個實現的方法。
  • Optional 類 :Optional 類已經成爲 Java 8 類庫的一部分,用來解決空指針異常。
  • Date Time API :增強對日期與時間的處理。

60. 匿名內部類是什麼?如何訪問在其外面定義的變量呢?

匿名內部類就是沒有名字的內部類,平常開發中使用的比較多。

public class Outer {

    private void test(final int i) {
        new Service() {
            public void method() {
                for (int j = 0; j < i; j++) {
                    System.out.println("匿名內部類" );
                }
            }
        }.method();
    }
 }
 //匿名內部類必須繼承或實現一個已有的接口 
 interface Service{
    void method();
}

複製代碼

匿名內部類還有如下特色:

  • 沒有名字
  • 匿名內部類必須繼承一個抽象類或者實現一個接口。
  • 匿名內部類不能定義任何靜態成員和靜態方法。
  • 當所在的方法的形參須要被匿名內部類使用時,必須聲明爲 final。
  • 匿名內部類不能是抽象的,它必需要實現繼承的類或者實現的接口的全部抽象方法。
  • 匿名內部類不能訪問外部類方法中的局部變量,除非該變量被聲明爲final類型

能夠看我這篇文章哈~Java程序員必備基礎:內部類解析

61. break和continue有什麼區別?

  • break可使流程跳出switch語句體,也能夠在循環結構終止本層循環體,從而提早結束本層循環。
  • continue的做用是跳過本次循環體中餘下還沒有執行的語句,當即進行下一次的循環條件斷定,能夠理解爲僅結束本次循環

62. String s = "Hello";s = s + " world!";這兩行代碼執行後,原始的 String 對象中的內容是否會改變?

沒有。由於 String 被設計成不可變(immutable)類,因此它的全部對象都是不可變對象。

63. String s="a"+"b"+"c"+"d";建立了幾個對象?

1個而已啦。

Java 編譯器對字符串常量直接相加的表達式進行優化,不等到運行期去進行加法運算,在編譯時就去掉了加號,直接將其編譯成一個這些常量相連的結果。因此 "a"+"b"+"c"+"d" 至關於直接定義一個 "abcd" 的字符串。

64. try-catch-finally-return執行順序

try-catch-finally-return 執行描述:

  • 若是不發生異常,不會執行catch部分。
  • 無論有沒有發生異常,finally都會執行到。
  • 即便try和catch中有return時,finally仍然會執行
  • finally是在return後面的表達式運算完後再執行的。(此時並無返回運算後的值,而是先把要返回的值保存起來,若finally中無return,則無論finally中的代碼怎麼樣,返回的值都不會改變,仍然是以前保存的值),該狀況下函數返回值是在finally執行前肯定的)
  • finally部分就不要return了,要否則,就回不去try或者catch的return了。

看一個例子

public static void main(String[] args) throws IOException {
        System.out.println("result:" + test());
    }

    private static int test() {
        int temp = 1;
        try {
            System.out.println("start execute try,temp is:"+temp);
            return ++temp;
        } catch (Exception e) {
            System.out.println("start execute catch temp is: "+temp);
            return ++temp;
        } finally {
            System.out.println("start execute finally,temp is:" + temp);
            ++temp;
        }
    }
複製代碼

運行結果:

start execute try,temp is:1
start execute finally,temp is:2
result:2
複製代碼

分析:

  • 先執行try部分,輸出日誌,執行++temp表達式,temp變爲2,這個值被保存起來。
  • 由於沒有發生異常,因此catch代碼塊跳過。
  • 執行finally代碼塊,輸出日誌,執行++temp表達式.
  • 返回try部分保存的值2.

65. Java 7新的 try-with-resources語句,平時有使用嗎

try-with-resources,是Java7提供的一個新功能,它用於自動資源管理。

  • 資源是指在程序用完了以後必需要關閉的對象。
  • try-with-resources保證了每一個聲明瞭的資源在語句結束的時候會被關閉
  • 什麼樣的對象才能當作資源使用呢?只要實現了java.lang.AutoCloseable接口或者java.io.Closeable接口的對象,都OK。

try-with-resources出現以前

try{
    //open resources like File, Database connection, Sockets etc
} catch (FileNotFoundException e) {
    // Exception handling like FileNotFoundException, IOException etc
}finally{
    // close resources
}
複製代碼

Java7,try-with-resources出現以後,使用資源實現

try(// open resources here){
    // use resources
} catch (FileNotFoundException e) {
    // exception handling
}
// resources are closed as soon as try-catch block is executed.
複製代碼

Java7使用資源demo

public class Java7TryResourceTest {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader(
                "C:/jaywei.txt"))) {
            System.out.println(br.readLine());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
複製代碼

使用了try-with-resources的好處

  • 代碼更加優雅,行數更少。
  • 資源自動管理,不用擔憂內存泄漏問題。

66. 簡述一下面向對象的」六原則一法則」。

  • 單一職責原則:一個類只作它該作的事情。
  • 開閉原則:軟件實體應當對擴展開放,對修改關閉。
  • 依賴倒轉原則:面向接口編程。
  • 接口隔離原則:接口要小而專,毫不能大而全。
  • 合成聚合複用原則:優先使用聚合或合成關係複用代碼。
  • 迪米特法則:迪米特法則又叫最少知識原則,一個對象應當對其餘對象有儘量少的瞭解。

67. switch是否能做用在byte 上,是否能做用在long 上,是否能做用在String上?

  • switch可做用於char byte short int
  • switch可做用於char byte short int對應的包裝類
  • switch不可做用於long double float boolean,以及他們的包裝類

68. 數組有沒有length()方法?String有沒有length()方法?

  • 數組沒有length()方法,而是length;
  • String有length()方法

69. 是否能夠從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?

不能夠。

  • 非static方法是要與對象實例息息相關的,必須在建立一個對象後,才能夠在該對象上進行非static方法調用,而static方法跟類相關的,不須要建立對象,能夠由類直接調用。
  • 當一個static方法被調用時,可能尚未建立任何實例對象,若是從一個static方法中發出對非static方法的調用,那個非static方法是關聯到哪一個對象上的呢?這個邏輯是不成立的
  • 所以,一個static方法內部不能夠發出對非static方法的調用。

70. String s = new String("jay");建立了幾個字符串對象?

一個或兩個

  • 第一次調用 new String("jay"); 時,會在堆內存中建立一個字符串對象,同時在字符串常量池中建立一個對象 "jay"
  • 第二次調用 new String("jay"); 時,只會在堆內存中建立一個字符串對象,指向以前在字符串常量池中建立的 "jay"

能夠看老王這篇文章,很清晰~ 別再問我 new 字符串建立了幾個對象了!我來證實給你看!

71. this和super關鍵字的做用

this:

  • 對象內部指代自身的引用
  • 解決成員變量和局部變量同名問題
  • 能夠調用成員變量,不能調用局部變量
  • 能夠調用成員方法
  • 在普通方法中能夠省略 this
  • 在靜態方法當中不容許出現 this 關鍵字

super:

  • 調用父類 的成員或者方法
  • 調用父類的構造函數

72. 咱們能將int強制轉換爲 byte類型的變量嗎?若是該值大於byte 類型的範圍,將會出現什麼現象?

能夠,咱們能夠作強制轉換,可是在Java中,int是32位,byte是8位,若是強制作轉化,int類型的高24位將會被丟棄。

public class Test {
    public static void main(String[] args)  {
        int a =129;
        byte b = (byte) a;
        System.out.println(b);
        int c =10;
        byte d = (byte) c;
        System.out.println(d);

    }
}
輸出:
-127
10
複製代碼

73. float f=3.4;正確嗎?

不正確,精度不許確,應該用強制類型轉換

74. 接口能否繼承接口?抽象類是否可實現接口?抽象類是否可繼承實體類?

均可以的

75. Reader和InputStream區別?

  • InputStream是表示字節輸入流的全部類的超類
  • Reader是用於讀取字符流的抽象類

76. 列舉出JAVA中6個比較經常使用的包

  • java.lang;
  • java.util;
  • java.io;
  • java.sql;
  • java.awt;
  • java.net;

77. JDK 7有哪些新特性

  • Try-with-resource語句
  • NIO2 文件處理Files
  • switch能夠支持字符串判斷條件
  • 泛型推導
  • 多異常統一處理

78. 同步和異步有什麼區別?

  • 同步,能夠理解爲在執行完一個函數或方法以後,一直等待系統返回值或消息,這時程序是出於阻塞的,只有接收到返回的值或消息後才往下執行其餘的命令。
  • 異步,執行完函數或方法後,沒必要阻塞性地等待返回值或消息,只須要向系統委託一個異步過程,那麼當系統接收到返回值或消息時,系統會自動觸發委託的異步過程,從而完成一個完整的流程。
  • 同步,就是實時處理(如打電話)
  • 異步,就是分時處理(如收發短信)

參考這篇文章~ 同步和異步的區別

79. 實際開發中,Java通常使用什麼數據類型來表明價格?

java中使用BigDecimal來表示價格是比較好的。

能夠看這篇文章,寫得很是好 老大說:誰要再用double定義商品金額,就本身收拾東西走

80. 64 位 JVM 中,int 的長度是多數?

int數據類型佔4個字節 32位,跟JVM位數不要緊的

公衆號

  • 歡迎關注我我的公衆號,交個朋友,一塊兒學習哈~
相關文章
相關標籤/搜索