1. 程式人生 > >04-撩課-Java面試寶典-第四篇

04-撩課-Java面試寶典-第四篇

31.靜態變數和例項變數的區別?
靜態變數也叫類變數,
這種變數前加了static修飾符。
可以直接用類名呼叫,
也可以用物件呼叫,
而且所有物件的同一個類變數 
都是共享同一塊記憶體空間。

例項變數也叫物件變數,
這種變數沒有加static修飾符。
只能通過物件呼叫, 
而且所有物件的同一個例項變數
是共享不同的記憶體空間的。

區別在於:
靜態變數是所有物件共有的,
某一個物件將它的值改變了,
其他物件再去獲取它的值,
得到的是改變後的值;
例項變數則是每一個物件私有的,
某一個物件將它的值改變了,
不影響其他物件取值的結果,
其他物件仍會得到例項變數
一開始就被賦予的值。

例項變數必須建立物件後
才可以通過這個物件來使用,
靜態變數
則可以直接使用類名來引用。
32.垃圾回收器的基本原理是什麼?
垃圾回收器是Java平臺中用的
最頻繁的一種物件銷燬方法。
垃圾回收器會全程偵測Java應用程式的執行情況。
當發現有些物件成為垃圾時,
垃圾回收器就會銷燬這些物件,
並釋放這些物件所佔用的記憶體空間。
在這裡,程式開發人員需要知道,
在哪些情況下垃圾回收器
會認為這些物件是垃圾物件。
通常情況下,如果發生以下兩種情況時,
系統會認為這些物件是垃圾物件,
需要銷燬。
一是將一個NULL值賦值給物件。
二是物件其超出了作用範圍,
33.垃圾回收器可以馬上回收記憶體嗎?
不會馬上回收,
只有在必須回收時才會回收,
或者你可以呼叫垃圾回收方法,
虛擬機器會在空閒時回收,
至於什麼時候回收,
虛擬機器說了算
34.有什麼辦法主動通知虛擬機器進行垃圾回收?
對於GC來說,
當程式設計師建立物件時,
GC就開始監控這個物件的地址、
大小以及使用情況。 
通常,GC採用有向圖的方式記錄和管理堆(heap)中的所有物件。
通過這種方式確定哪些物件是”可達的”,
哪些物件是”不可達的”。
當GC確定一些物件為”不可達”時,
GC就有責任回收這些記憶體空間。
可以。程式設計師可以手動執行System.gc(),
通知GC執行,
但是Java語言規範
並不保證GC一定會執行。

System.gc()的工作原理
Java中的記憶體分配
是隨著new一個新的物件來實現的,
這個很簡單,
而且也還是有一些
可以“改進”記憶體回收的機制的,
其中最顯眼的
就是這個System.gc()函式。

乍一看這個函式似乎是可以進行垃圾回收的,
可事實並不是那麼簡單。
其實這個gc()函式的作用只是提醒虛擬機器:
程式設計師希望進行一次垃圾回收。
但是它不能保證垃圾回收一定會進行,
而且具體什麼時候進行
是取決於具體的虛擬機器的,
不同的虛擬機器有不同的對策。
35.內部類可以引用他包含類的成員嗎?
完全可以。
如果不是靜態內部類,
那沒有什麼限制! 
一個內部類物件可以訪問
建立它的外部類物件的成員包括私有成員。
如果你把靜態巢狀類當作內部類的一種特例,
那在這種情況下不可以訪問外部類的
普通成員變數,
而只能訪問外部類中的靜態成員。

內部類的訪問規則:
1、內部類可以直接訪問外部類中的成員,
包括私有。
之所以可以直接訪問外部類中的成員,
是因為內部類中持有了
一個外部類的引用,
格式 外部類名.this
2、外部類要訪問內部類,必須建立內部類物件。

內部類定義在區域性時,
1、不可以被成員修飾符修飾
2、可以直接訪問外部類中的成員,
因為還持有外部類中的引用。
但是不可以訪問它所在的區域性中的變數。
只能訪問被final修飾的區域性變數。

36.Java 中的異常處理機制的簡單原理和應用?
 一、Execption可以分為
java標準定義的異常
程式設計師自定義異常2種
1.一種是當程式違反了java語規則的時候,
JAVA虛擬機器就會將發生的錯誤
表示為一個異常.
這裡語法規則指的是
JAVA類庫內建的語義檢查。
例如 int i = 2 / 0 
或者 String str = null;str.length();

2.另一種情況就是JAVA允許程式設計師
擴充套件這種語義檢查,
程式設計師可以建立自己的異常,
並自由選擇在何時用throw關鍵字
引發異常。

例如 Exception ex = new Exception("這是我自定義的異常;
throw ex;

所有的異常都是Thowable的子類。
異常處理是與程式執行是並行的。

二、異常的處理方式
1.捕獲異常

 try {
  int i = 2 / 0;
 } catch (Exception ex) {
   ex.printStackTrace();
   System.out.println("異常資訊:" + ex.getMessage());
}

2.上拋異常 throws
public void test() throws Exception { 
    String str = null;
    str.length();
}
37.執行時異常與一般異常有何異同?
(1)執行時異常
都是RuntimeException類
及其子類異常,
如NullPointerException、
IndexOutOfBoundsException等,
這些異常是不檢查異常,
程式中可以選擇捕獲處理,
也可以不處理。
這些異常一般是由程式邏輯錯誤引起的,
程式應該從邏輯角度
儘可能避免這類異常的發生。

當出現RuntimeException的時候,
我們可以不處理。
當出現這樣的異常時,
總是由虛擬機器接管。
比如:我們從來沒有人
去處理過NullPointerException異常,
它就是執行時異常,
並且這種異常還是最常見的異常之一。

出現執行時異常後,
系統會把異常一直往上層拋,
一直遇到處理程式碼。
如果沒有處理塊,
到最上層,
如果是多執行緒就由Thread.run()丟擲,
如果是單執行緒就被main()丟擲。
丟擲之後,
如果是執行緒,
這個執行緒也就退出了。
如果是主程式丟擲的異常,
那麼這整個程式也就退出了。
執行時異常是Exception的子類,
也有一般異常的特點,
是可以被Catch塊處理的。
只不過往往我們不對他處理罷了。
也就是說,
你如果不對執行時異常進行處理,
那麼出現執行時異常之後,
要麼是執行緒中止,
要麼是主程式終止。 

如果不想終止,
則必須撲捉所有的執行時異常,
決不讓這個處理執行緒退出。
佇列裡面出現異常資料了,
正常的處理應該是把異常資料捨棄,
然後記錄日誌。
不應該由於異常資料
而影響下面對正常資料的處理。

(2)非執行時異常
是RuntimeException以外的異常,
型別上都屬於Exception類及其子類。
如 IOException、SQLException 等
以及使用者自定義的Exception異常。
對於這種異常,
JAVA編譯器強制要求我們
必需對出現的這些異常進行catch並處理,
否則程式就不能編譯通過。
所以,面對這種異常不管我們是否願意,
只能自己去寫一大堆catch塊
去處理可能的異常。
38.為什麼Map介面不繼承Collection 介面?
Collection是最基本的集合介面,
聲明瞭適用於JAVA集合(只包括Set和List)
的通用方法。 
Set 和List 都繼承了Conllection;
Set具有與Collection完全一樣的介面,
因此沒有任何額外的功能,
不像前面有兩個不同的List。
實際上Set就是Collection,只 是行為不同。
(這是繼承與多型思想的典型應用:表現不同的行為。)
Set不儲存重複的元素(至於如何判斷元素相同則較為負責) 

 Map沒有繼承於Collection介面 
從Map集合中檢索元素時,
只要給出鍵物件,
就會返回對應的值物件。 


Collection 和 Map 的區別
容器內每個為之所儲存的元素個數不同。
Collection型別者,
每個位置只有一個元素。
Map型別者,
持有 key-value pair,
像個小型資料庫

儘管Map介面和它的實現也是集合框架的一部分,
但Map不是集合,
集合也不是Map。
因此,Map繼承Collection毫無意義,
反之亦然。
如果Map繼承Collection介面,
那麼元素去哪兒?
Map包含key-value對,
它提供抽取key或value列表集合的方法,
但是它不適合“一組物件”規範。

39.comparable 和 comparator的不同之處?
Comparable可以認為是一個內比較器,
實現了Comparable介面的類有一個特點,
就是這些類是可以和自己比較的,
至於具體和另一個實現了Comparable介面的類如何比較,
則依賴compareTo方法的實現,
compareTo方法也被稱為自然比較方法。
如果開發者add進入
一個Collection的物件想要Collections的sort方法
幫你自動進行排序的話,
那麼這個物件必須實現Comparable介面。
compareTo方法的返回值是int,
有三種情況:
1、比較者大於被比較者
(也就是compareTo方法裡面的物件),
那麼返回正整數
2、比較者等於被比較者,那麼返回0
3、比較者小於被比較者,那麼返回負整數


Comparator可以認為是是一個外比較器,
個人認為有兩種情況
可以使用實現Comparator介面的方式:
1、一個物件不支援自己和自己比較
(沒有實現Comparable介面),
但是又想對兩個物件進行比較
2、一個物件實現了Comparable介面,
但是開發者認為compareTo方法中的
比較方式並不是自己想要的那種比較方式

Comparator接口裡面有一個compare方法,
方法有兩個引數T o1和T o2,
是泛型的表示方式,
分別表示待比較的兩個物件,
方法返回值和Comparable介面一樣是int,
有三種情況:
1、o1大於o2,返回正整數
2、o1等於o2,返回0
3、o1小於o2,返回負整數

總結
兩種比較器Comparable和Comparator,
後者相比前者有如下優點:
1、如果實現類沒有實現Comparable介面,
又想對兩個類進行比較
或者實現類實現了Comparable介面,
但是對compareTo方法內的比較演算法不滿意,
那麼可以實現Comparator介面,
自定義一個比較器,
寫比較演算法

2、實現Comparable介面的方式比
實現Comparator介面的耦合性要強一些,
如果要修改比較演算法,
要修改Comparable介面的實現類,
而實現Comparator的類是在外部進行比較的,
不需要對實現類有任何修 改。
從這個角度說,
其實有些不太好,
尤其在我們將實現類的.class檔案
打成一個.jar檔案
提供給開發者使用的時候。
實際上實現Comparator 介面的方式
後面會寫到就是一種典型的策略模式。

當然,這不是鼓勵用Comparator,
意思是開發者還是要在具體場景下
選擇最合適的那種比較器而已。

學習地址:
撩課-JavaWeb系列1之基礎語法-前端基礎
撩課-JavaWeb系列2之XML
撩課-JavaWeb系列3之MySQL
撩課-JavaWeb系列4之JDBC
撩課-JavaWeb系列5之web伺服器-idea