1. 程式人生 > 其它 >最新精選Java面試題及答案,Java基礎面試題答案精選(八)

最新精選Java面試題及答案,Java基礎面試題答案精選(八)


上圖是我整理的Java面試題合集,包攬了基本所有技術棧:完整版Java面試題合集附答案,高清PDF下載

1. 為什麼要有包裝型別?

讓基本資料型別也具有物件的特徵

基本型別 包裝器型別
boolean Boolean
char Character
int Integer
byte Byte
short Short
long Long
float Float
double Double

為了讓基本型別也具有物件的特徵,就出現了包裝型別(如我們在使用集合型別Collection時就一定要使用包裝型別而非基本型別)因為容器都是裝object的,這是就需要這些基本型別的包裝器類了。

自動裝箱:new Integer(6);,底層呼叫:Integer.valueOf(6)

自動拆箱: int i = new Integer(6);,底層呼叫i.intValue();方法實現。

Integer i  = 6;
Integer j = 6;
System.out.println(i==j);

答案在下面這段程式碼中找:

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

二者的區別:

  1. 宣告方式不同:基本型別不使用new關鍵字,而包裝型別需要使用new關鍵字來在堆中分配儲存空間
  2. 儲存方式及位置不同:基本型別是直接將變數值儲存在棧中,而包裝型別是將物件放在堆中,然後通過引用來使用;
  3. 初始值不同:基本型別的初始值如int為0,boolean為false,而包裝型別的初始值為null;
  4. 使用方式不同:基本型別直接賦值直接使用就好,而包裝型別在集合如Collection、Map時會使用到。

2. 成員變數與區域性變數的區別有哪些

  • 變數:在程式執行的過程中,在某個範圍內其值可以發生改變的量。從本質上講,變數其實是記憶體中的一小塊區域

  • 成員變數:方法外部,類內部定義的變數

  • 區域性變數:類的方法中的變數。

  • 成員變數和區域性變數的區別

作用域

  • 成員變數:針對整個類有效。
  • 區域性變數:只在某個範圍內有效。(一般指的就是方法,語句體內)

儲存位置

  • 成員變數:隨著物件的建立而存在,隨著物件的消失而消失,儲存在堆記憶體中。
  • 區域性變數:在方法被呼叫,或者語句被執行的時候存在,儲存在棧記憶體中。當方法呼叫完,或者語句結束後,就自動釋放。

生命週期

  • 成員變數:隨著物件的建立而存在,隨著物件的消失而消失
  • 區域性變數:當方法呼叫完,或者語句結束後,就自動釋放。

初始值

  • 成員變數:有預設初始值。
  • 區域性變數:沒有預設初始值,使用前必須賦值。

3. 訪問修飾符 public,private,protected,以及不寫(預設)時的區別

  • 定義:Java中,可以使用訪問修飾符來保護對類、變數、方法和構造方法的訪問。Java 支援 4 種不同的訪問許可權。

  • 分類

    • private : 在同一類內可見。使用物件:變數、方法。 注意:不能修飾類(外部類)

    • default (即預設,什麼也不寫,不使用任何關鍵字): 在同一包內可見,不使用任何修飾符。使用物件:類、介面、變數、方法。

    • protected : 對同一包內的類和所有子類可見。使用物件:變數、方法。 注意:不能修飾類(外部類)。

    • public : 對所有類可見。使用物件:類、介面、變數、方法

訪問修飾符圖

4. 構造方法有哪些特性?

  • 名字與類名相同;

  • 沒有返回值,但不能用void宣告建構函式;

  • 生成類的物件時自動執行,無需呼叫。

5. 什麼是受檢異常

異常表示程式執行過程中可能出現的非正常狀態。

執行時異常表示 虛擬機器的通常操作中可能遇到的異常,是一種常見執行錯誤,只要程式設計得沒有問題通常就不會發生。

受檢異常 跟程式執行的上下文環境有關,即使程式設計無誤,仍然可能因使用的問題而引發。

Java 編譯器要求方法必須宣告丟擲可能發生的受檢異常,但是並不要求必須宣告丟擲未被捕獲的執行時異常。異常和繼承一樣,是面向物件程式設計中經常被濫用的東西,在 Effective Java 中對異常的使用給出了以下指導原則:

1、 不要將異常處理用於正常的控制流(設計良好的 API 不應該強迫它的呼叫者為了正常的控制流而使用異常)

2、 對可以恢復的情況使用受檢異常,對程式設計錯誤使用執行時異常

3、 避免不必要的使用受檢異常(可以通過一些狀態檢測手段來避免異常的發生)

4、 優先使用標準的異常

5、 每個方法丟擲的異常都要有文件

6、 保持異常的原子性

7、 不要在 catch 中忽略掉捕獲到的異常

6. Java的四種引用,強弱軟虛

  • 強引用

    強引用是平常中使用最多的引用,強引用在程式記憶體不足(OOM)的時候也不會被回收,使用方式:

String str = new String("str");
  • 軟引用

    軟引用在程式記憶體不足時,會被回收,使用方式:

// 注意:wrf這個引用也是強引用,它是指向SoftReference這個物件的,
// 這裡的軟引用指的是指向new String("str")的引用,也就是SoftReference類中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));

可用場景: 建立快取的時候,建立的物件放進快取中,當記憶體不足時,JVM就會回收早先建立的物件。

  • 弱引用

    弱引用就是隻要JVM垃圾回收器發現了它,就會將之回收,使用方式:

WeakReference<String> wrf = new WeakReference<String>(str);

可用場景: Java原始碼中的java.util.WeakHashMap中的key就是使用弱引用,我的理解就是,一旦我不需要某個引用,JVM會自動幫我處理它,這樣我就不需要做其它操作。

  • 虛引用

    虛引用的回收機制跟弱引用差不多,但是它被回收之前,會被放入ReferenceQueue中。注意哦,其它引用是被JVM回收後才被傳入ReferenceQueue中的。由於這個機制,所以虛引用大多被用於引用銷燬前的處理工作。還有就是,虛引用建立的時候,必須帶有ReferenceQueue,使用例子:

PhantomReference<String> prf = new PhantomReference<String>(new String("str"), new ReferenceQueue<>());

可用場景: 物件銷燬前的一些操作,比如說資源釋放等。**Object.finalize()雖然也可以做這類動作,但是這個方式即不安全又低效

上訴所說的幾類引用,都是指物件本身的引用,而不是指Reference的四個子類的引用(SoftReference等)。

7. 陣列有沒有 length()方法?String 有沒有 length()方法

  • 陣列沒有 length()方法 ,有 length 的屬性。String 有 length()方法。JavaScript中,獲得字串的長度是通過 length 屬性得到的,這一點容易和 Java 混淆。

8. Java 中有幾種型別的流?

從輸入輸出方面來講: Java中有輸入流和輸出流

從流的編碼方式上來講: Java中有位元組流和字元流

對於位元組流而言:主要繼承的抽象類為 InputStream和OutputStream

對於字元流而言:主要繼承的抽象類為 InputStreamReader和OutputStreamReder

9. 反射機制的應用場景有哪些?

  • 反射是框架設計的靈魂。

  • 在我們平時的專案開發過程中,基本上很少會直接使用到反射機制,但這不能說明反射機制沒有用,實際上有很多設計、開發都與反射機制有關,例如模組化的開發,通過反射去呼叫對應的位元組碼;動態代理設計模式也採用了反射機制,還有我們日常使用的 Spring/Hibernate 等框架也大量使用到了反射機制。

  • 舉例:①我們在使用JDBC連線資料庫時使用Class.forName()通過反射載入資料庫的驅動程式;②Spring框架也用到很多反射機制,最經典的就是xml的配置模式。Spring 通過 XML 配置模式裝載 Bean 的過程:1) 將程式內所有 XML 或 Properties 配置檔案載入入記憶體中; 2)Java類裡面解析xml或properties裡面的內容,得到對應實體類的位元組碼字串以及相關的屬性資訊; 3)使用反射機制,根據這個字串獲得某個類的Class例項; 4)動態配置例項的屬性

10. final有哪些用法?

final也是很多面試喜歡問的地方,但我覺得這個問題很無聊,通常能回答下以下5點就不錯了:

  • 被final修飾的類不可以被繼承
  • 被final修飾的方法不可以被重寫
  • 被final修飾的變數不可以被改變.如果修飾引用,那麼表示引用不可變,引用指向的內容可變.
  • 被final修飾的方法,JVM會嘗試將其內聯,以提高執行效率
  • 被final修飾的常量,在編譯階段會存入常量池中.

除此之外,編譯器對final域要遵守的兩個重排序規則更好:

在建構函式內對一個final域的寫入,與隨後把這個被構造物件的引用賦值給一個引用變數,這兩個操作之間不能重排序 初次讀一個包含final域的物件的引用,與隨後初次讀這個final域,這兩個操作之間不能重排序.

11. 講講NIO

看了一些文章,傳統的IO流是阻塞式的,會一直監聽一個ServerSocket,在呼叫read等方法時,他會一直等到資料到來或者緩衝區已滿時才返回。

呼叫accept也是一直阻塞到有客戶端連線才會返回。每個客戶端連線過來後,服務端都會啟動一個執行緒去處理該客戶端的請求。並且多執行緒處理多個連線。每個執行緒擁有自己的棧空間並且佔用一些 CPU 時間。每個執行緒遇到外部未準備好的時候,都會阻塞掉。阻塞的結果就是會帶來大量的程序上下文切換。
對於NIO,它是非阻塞式,核心類:
1、 Buffer為所有的原始型別提供 (Buffer)快取支援。
2、 Charset字符集編碼解碼解決方案
3、 Channel一個新的原始 I/O抽象,用於讀寫Buffer型別,通道可以認為是一種連線,可以是到特定裝置,程式或者是網路的連線。

12. Java有哪些資料型別

Java有 8 種基本資料型別,分別為:

  • 6 種數字型別 (四個整數形,兩個浮點型):byte、short、int、long、float、double

  • 1 種字元型別:char

  • 1 種布林型:boolean。

byte:

  • byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數;
  • 最小值是 -128(-2^7)
  • 最大值是 127(2^7-1)
  • 預設值是 0
  • byte 型別用在大型陣列中節約空間,主要代替整數,因為 byte 變數佔用的空間只有 int 型別的四分之一;
  • 例子:byte a = 100,byte b = -50。

short:

  • short 資料型別是 16 位、有符號的以二進位制補碼錶示的整數
  • 最小值是 -32768(-2^15)
  • 最大值是 32767(2^15 - 1)
  • Short 資料型別也可以像 byte 那樣節省空間。一個short變數是int型變數所佔空間的二分之一;
  • 預設值是 0
  • 例子:short s = 1000,short r = -20000。

int:

  • int 資料型別是32位、有符號的以二進位制補碼錶示的整數;
  • 最小值是 -2,147,483,648(-2^31)
  • 最大值是 2,147,483,647(2^31 - 1)
  • 一般地整型變數預設為 int 型別;
  • 預設值是 0
  • 例子:int a = 100000, int b = -200000。

long:

  • 注意:Java 裡使用 long 型別的資料一定要在數值後面加上 L,否則將作為整型解析

  • long 資料型別是 64 位、有符號的以二進位制補碼錶示的整數;

  • 最小值是 -9,223,372,036,854,775,808(-2^63)

  • 最大值是 9,223,372,036,854,775,807(2^63 -1)

  • 這種型別主要使用在需要比較大整數的系統上;

  • 預設值是 0L

  • 例子: long a = 100000L,Long b = -200000L。
    "L"理論上不分大小寫,但是若寫成"l"容易與數字"1"混淆,不容易分辯。所以最好大寫。

float:

  • float 資料型別是單精度、32位、符合IEEE 754標準的浮點數;
  • float 在儲存大型浮點陣列的時候可節省記憶體空間;
  • 預設值是 0.0f
  • 浮點數不能用來表示精確的值,如貨幣;
  • 例子:float f1 = 234.5f。

double:

  • double 資料型別是雙精度、64 位、符合IEEE 754標準的浮點數;
  • 浮點數的預設型別為double型別;
  • double型別同樣不能表示精確的值,如貨幣;
  • 預設值是 0.0d
  • 例子:double d1 = 123.4。

char:

  • char型別是一個單一的 16 位 Unicode 字元;
  • 最小值是 \u0000(即為 0);
  • 最大值是 \uffff(即為 65535);
  • char 資料型別可以儲存任何字元;
  • 例子:char letter = 'A';(單引號

boolean:

  • boolean資料型別表示一位的資訊;
  • 只有兩個取值:true 和 false;
  • 這種型別只作為一種標誌來記錄 true/false 情況;
  • 預設值是 false
  • 例子:boolean one = true。

這八種基本型別都有對應的包裝類分別為:Byte、Short、Integer、Long、Float、Double、Character、Boolean

型別名稱 位元組、位數 最小值 最大值 預設值 例子
byte位元組 1位元組,8位 -128(-2^7) 127(2^7-1) 0 byte a = 100,byte b = -50
short短整型 2位元組,16位 -32768(-2^15) 32767(2^15 - 1) 0 short s = 1000,short r = -20000
int整形 4位元組,32位 -2,147,483,648(-2^31) 2,147,483,647(2^31 - 1) 0 int a = 100000, int b = -200000
lang長整型 8位元組,64位 -9,223,372,036,854,775,808(-2^63) 9,223,372,036,854,775,807(2^63 -1) 0L long a = 100000L,Long b = -200000L
double雙精度 8位元組,64位 double型別同樣不能表示精確的值,如貨幣 0.0d double d1 = 123.4
float單精度 4位元組,32位 在儲存大型浮點陣列的時候可節省記憶體空間 不同統計精準的貨幣值 0.0f float f1 = 234.5f
char字元 2位元組,16位 \u0000(即為0) \uffff(即為65,535) 可以儲存任何字元 char letter = 'A';
boolean布林 返回true和false兩個值 這種型別只作為一種標誌來記錄 true/false 情況; 只有兩個取值:true 和 false; false boolean one = true

13. 靜態變數和例項變數區別

  • 靜態變數: 靜態變數由於不屬於任何例項物件,屬於類的,所以在記憶體中只會有一份,在類的載入過程中,JVM只為靜態變數分配一次記憶體空間。

  • 例項變數: 每次建立物件,都會為每個物件分配成員變數記憶體空間,例項變數是屬於例項物件的,在記憶體中,建立幾次物件,就有幾份成員變數。

14. error和exception有什麼區別?

error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說記憶體溢位。不可能指望程式能處理這樣的情況。exception表示一種設計或實現問題。也就是說,它表示如果程式執行正常,從不會發生的情況。

15. 有哪些可用的Filter流?

在java.io包中主要由4個可用的filter Stream組成。兩個位元組filter stream,兩個字元filter stream。分別是:FilterInputStreamFilterOutputStreamFilterReaderFilterWriter