最新精選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); }
二者的區別:
- 宣告方式不同:基本型別不使用new關鍵字,而包裝型別需要使用new關鍵字來在堆中分配儲存空間;
- 儲存方式及位置不同:基本型別是直接將變數值儲存在棧中,而包裝型別是將物件放在堆中,然後通過引用來使用;
- 初始值不同:基本型別的初始值如int為0,boolean為false,而包裝型別的初始值為null;
- 使用方式不同:基本型別直接賦值直接使用就好,而包裝型別在集合如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。分別是:FilterInputStream
、FilterOutputStream
、FilterReader
和FilterWriter
。