贏在面試之Java基礎篇(1)

1、解釋Java面向對象的特徵: 抽象、封裝、繼承、多態。

抽象:抽象是將一類對象的共同特徵總結出來構造類的過程,包括數據抽象和行爲抽象兩方面。
抽象只關注對象有哪些屬性和行爲,並不關注這些行爲的細節是什麼。

繼承:繼承是從已有類得到繼承信息創建新類的過程。提供繼承信息的類被稱爲父類(超類、基類);得到繼承信息的類被稱爲子類(派生類)。繼承讓變化中的軟件系統有了一定的延續性,同時繼承也是封裝程序中可變因素的重要手段。繼承提高了代碼的複用性。繼承的出現讓類與類之間產生了關係,提供了多態的前提。

封裝:通常認爲封裝是把數據和操作數據的方法綁定起來,對數據的訪問只能通過已定義的接口。
好處:• 將變化隔離。• 便於使用。• 提高重用性。• 提高安全性。
封裝原則:• 將不需要對外提供的內容都隱藏起來。• 把屬性都隱藏,提供公共方法對其訪問。
Java中可以通過對類的成員設置一定的訪問權限,實現類中成員的信息隱藏:
• private:類中限定爲private的成員,只能被這個類本身訪問。如果一個類的構造方法聲明爲private,則其它類不能生成該類的一個實例。
• default:類中不加任何訪問權限限定的成員屬於缺省的(default)訪問狀態,可以被這個類本身和同一個包中的類所訪問。
• protected:類中限定爲protected的成員,可以被這個類本身、它的子類(包括同一個包中以及不同包中的子類)和同一個包中的所有其他的類訪問。
• public:類中限定爲public的成員,可以被所有的類訪問。

多態性:多態性是指允許不同子類型的對象對同一消息作出不同的響應。
簡單的說就是用同樣的對象引用調用同樣的方法但是做了不同的事情。多態性分爲編譯時的多態性和運行時的多態性。
方法重載(overload)實現的是編譯時的多態性(也稱爲前綁定),而方法重寫(override)實現的是運行時的多態性(也稱爲後綁定)。
運行時的多態是面向對象最精髓的東西,要實現多態需要做兩件事:
1). 方法重寫(子類繼承父類並重寫父類中已有的或抽象的方法);
2). 對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行爲)。

2、面向對象的好處是什麼?

優點:

1、易維護

採用面向對象思想設計的結構,可讀性高,由於繼承的存在,即使改變需求,那麼維護也只是在局部模塊,所以維護起來是非常方便和較低成本的。

2、質量高

在設計時,可重用現有的,在以前的項目的領域中已被測試過的類使系統滿足業務需求並具有較高的質量。

3、效率高

在軟件開發時,根據設計的需要對現實世界的事物進行抽象,產生類。使用這樣的方法解決問題,接近於日常生活和自然的思考方式,勢必提高軟件開發的效率和質量。

4、易擴展

由於繼承、封裝、多態的特性,自然設計出高內聚、低耦合的系統結構,使得系統更靈活、更容易擴展,而且成本較低。

3、Java常用的關鍵字、修飾符的使用

private:類中限定爲private的成員,只能被這個類本身訪問。如果一個類的構造方法聲明爲private,則其它類不能生成該類的一個實例。
• default:類中不加任何訪問權限限定的成員屬於缺省的(default)訪問狀態,可以被這個類本身和同一個包中的類所訪問。
• protected:類中限定爲protected的成員,可以被這個類本身、它的子類(包括同一個包中以及不同包中的子類)和同一個包中的所有其他的類訪問。
• public:類中限定爲public的成員,可以被所有的類訪問。
• static:static可以用來修飾class、field、method等,被static修飾的關鍵字都存在於堆內存中,也即其生命週期一般是整個應用生命週期,static修飾的field又叫做全局變量,可以在整個類包括其子類中被使用,static修飾的class一般用於靜態內部類,是一個類的靜態成員,外部可以直接通過類名.靜態內部類名來訪問,可用new關鍵字,保證該類所有實例共享一個內存空間;static修飾method,可以不用該方法所屬類的實例,直接通過該方法名調用該方法,該方法作爲一個對象存放在堆內存中的靜態方法區。
• final:可以用來修飾class、field、method,final關鍵字的作用表明該field或class是一個常量,只能進行一次初始化。
• volatile:一般用於修飾field,保證改數據的內存可見性以及防止jvm對指令進行重排,其原理是:線程A中,cpu執行修改改field時,會先將各種數據加入計算機的緩存中,執行完了後,在寫回緩存裏面,最後在某個時間,對應線程再讀回到主存中,但這樣會導致內存可見性安全問題。使用volatile關鍵字,保證了每個線程都會從主存中去讀取該field的值,執行完成後再寫回主存中,而不經過緩存,以此來保證線程安全。
• synchronized:該關鍵字一般用於保證線程安全,可以直接修飾class的某個實例、class、method、field等,修飾class的某個實例表示,獲取這個實例的對應monitor,只有該monitor沒有被其他線程佔用時,纔可以進入該代碼段,修飾class或static時,表示這一類的所有實例都只能同時有一個線程進行訪問。修飾field和method和修飾實例差不多。
• transient:此關鍵字修飾的field表示該field被序列化時,此對象的值不可見,只存在於當前內存中。
• strictfp:浮點精度統一,用來修飾類、接口或方法,以此來限制該類的所有float和double都遵循統一的IEEE 754 標準,在不同的操作系統平臺環境下都產生同樣的值。

4、Java中的參數傳遞(值傳遞、引用傳遞)

值傳遞:(形式參數類型是基本數據類型和String):方法調用時,實際參數把它的值傳遞給對應的形式參數,形式參數只是用實際參數的值初始化自己的存儲單元內容,是兩個不同的存儲單元,所以方法執行中形式參數值的改變不影響實際參數的值。
按值傳遞:指的是在方法調用時,傳遞的參數是按值的拷貝傳遞。傳遞的是值的拷貝,也就是說傳遞後就互不相關了。
引用傳遞:(形式參數類型是引用數據類型參數除去String):也稱爲傳地址。方法調用時,實際參數是對象(或數組),這時實際參數與形式參數指向同一個地址,在方法執行中,對形式參數的操作實際上就是對實際參數的操作,這個結果在方法結束後被保留了下來,所以方法執行中形式參數的改變將會影響實際參數。
按引用傳遞:指的是在方法調用時,傳遞的是引用的地址,也就是變量所對應的內存空間的地址。,也就是說傳遞前和傳遞後都指向同一個引用(也就是同一個內存空間)。

5、簡述內部類、靜態內部類、匿名內部類的區別

內部類:成員內部類可訪問外部類所有的方法和成員變量。不能有靜態的方法和成員變量。

靜態內部類:只能訪問外部類的靜態成員變量與靜態方法。靜態內部類的非靜態成員可訪問外部類的靜態變量,而不可訪問外部類的非靜態變量。

匿名內部類:沒有類名,沒有class關鍵字也沒有extends和implements等關鍵字修飾。類的定義和對象的實例化同時進行。

6、try catch finally的使用

1.finally 裏 始終會被執行到, System.exit(0); 除這種被執行外。
2.即使try中有return ,也是先執行 return 後面的語句完了之後,不立馬return,而是去執行finally中的語句。
3.當try中與finally裏,同時出現return , 則只會返回 finally 中的return 結果。
4.finally中的值不能影響try中 即將返回的結果值。
注意: 若finally中沒有return在try或catch中有return,那麼在執行return跟着語句之後,會把語句的結果新開闢一內存空間,直接把結果的存放此內存空間中。所以,finally中的值不能影響try或catch中即將return的結果。

7、String 是最基本的數據類型嗎?

不是。Java中的基本數據類型只有8個:byte、short、int、long、float、double、char、boolean;除了基本類型(primitive type)和枚舉類型(enumeration type),剩下的都是引用類型(reference type)。

8、float f=3.4;是否正確?

不正確。3.4是雙精度數,將雙精度型(double)賦值給浮點型(float)屬於下轉型(down-casting,也稱爲窄化)會造成精度損失,因此需要強制類型轉換float f =(float)3.4; 或者寫成float f =3.4F;。

單精度和雙精度的區別就是,雙精度要比單精度所存儲的位數要多,至於說3.14是雙精度,是因爲Java中,默認的小數都是double類型,也就算雙精度的,如果要定義單精度的話,那就要在小數的後面加上一個f或者F,即 double d = 3.14; float f = 3.14f; 一定要注意後面有沒有“f”和“F”啊。

9、解釋內存中的棧(stack)、堆(heap)和靜態存儲區的用法。

通常我們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用內存中的棧空間;而通過new關鍵字和構造器創建的對象放在堆空間;程序中的字面量(literal)如直接書寫的100、“hello”和常量都是放在靜態存儲區中。棧空間操作最快但是也很小,通常大量的對象都是放在堆空間,整個內存包括硬盤上的虛擬內存都可以被當成堆空間來使用。

String str = new String(“hello”);


上面的語句中str放在棧上,用new創建出來的字符串對象放在堆上,而“hello”這個字面量放在靜態存儲區。

補充:較新版本的Java中使用了一項叫“逃逸分析“的技術,可以將一些局部對象放在棧上以提升對象的操作性能。

10、簡述while語句和do-while語句的特點與區別

while語句的特點是先判斷表達式後,執行循環體。如果一開始while循環的布爾表達式的值是false,那麼循環體根本就不執行。

Do-while語句先執行循環體,然後判斷循環條件是否成立,因此總是執行它的循環體至少一次。

11、swtich 是否能作用在byte 上,是否能作用在long 上,是否能作用在String上?

早期的JDK中,switch(expr)中,expr可以是byte、short、char、int。從1.5版開始,Java中引入了枚舉類型(enum),expr也可以是枚舉,從JDK 1.7版開始,還可以是字符串(String)。長整型(long)是不可以的。

12、數組有沒有length()方法?String 有沒有length()方法?

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

13、在Java 中,如何跳出當前的多重嵌套循環?

在最外層循環前加一個標記如A,然後用break A;可以跳出多重循環。(Java中支持帶標籤的break和continue語句,作用有點類似於C和C++中的goto語句,但是就像要避免使用goto一樣,應該避免使用帶標籤的break和continue,因爲它不會讓你的程序變得更優雅,很多時候甚至有相反的作用,所以這種語法其實不知道更好)

14、構造器(constructor)是否可被重寫(override)?

構造器不能被繼承,因此不能被重寫,但可以被重載。

15、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?

不對,如果兩個對象x和y滿足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:(1)如果兩個對象相同(equals方法返回true),那麼它們的hashCode值一定要相同;(2)如果兩個對象的hashCode相同,它們並不一定相同。當然,你未必要按照要求去做,但是如果你違背了上述原則就會發現在使用容器時,相同的對象可以出現在Set集合中,同時增加新元素的效率會大大下降(對於使用哈希存儲的系統,如果哈希碼頻繁的衝突將會造成存取性能急劇下降)。

16、是否可以繼承String 類?

String 類是final類,不可以被繼承。

補充:繼承String本身就是一個錯誤的行爲,對String類型最好的重用方式是關聯(HAS-A)而不是繼承(IS-A)。

17、當一個對象被當作參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裏到底是值傳遞還是引用傳遞?

是值傳遞。Java 編程語言只有值傳遞參數。當一個對象實例作爲一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性可以在被調用過程中被改變,但對象的引用是永遠不會改變的。C++和C#中可以通過傳引用或傳輸出參數來改變傳入的參數的值。

補充:Java中沒有傳引用實在是非常的不方便,這一點在Java 8中仍然沒有得到改進,正是如此在Java編寫的代碼中才會出現大量的Wrapper類(將需要通過方法調用修改的引用置於一個Wrapper類中,再將Wrapper對象傳入方法),這樣的做法只會讓代碼變得臃腫,尤其是讓從C和C++轉型爲Java程序員的開發者無法容忍。

18、抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被synchronized修飾?

都不能。抽象方法需要子類重寫,而靜態的方法是無法被重寫的,因此二者是矛盾的。本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized和方法的實現細節有關,抽象方法不涉及實現細節,因此也是相互矛盾的。

19、靜態變量和實例變量的區別?

靜態變量是被static修飾符修飾的變量,也稱爲類變量,它屬於類,不屬於類的任何一個對象,一個類不管創建多少個對象,靜態變量在內存中有且僅有一個拷貝;實例變量必須依存於某一實例,需要先創建對象然後通過對象才能訪問到它。靜態變量可以實現讓多個對象共享內存。在Java開發中,上下文類和工具類中通常會有大量的靜態成員。

20、是否可以從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?

不可以,靜態方法只能訪問靜態成員,因爲非靜態方法的調用要先創建對象,因此在調用靜態方法時可能對象並沒有被初始化。

21、如何實現對象克隆?

有兩種方式:

1.實現Cloneable接口並重寫Object類中的clone()方法;

2.實現Serializable接口,通過對象的序列化和反序列化實現克隆,可以實現真正的深度克隆

22、Anonymous Inner Class(匿名內部類)是否可以繼承其它類?是否可以實現接口?

可以繼承其他類或實現其他接口,在Swing編程中常用此方式來實現事件監聽和回調。

23、Java 中的final關鍵字有哪些用法?

(1)修飾類:表示該類不能被繼承;(2)修飾方法:表示方法不能被重寫;(3)修飾變量:表示變量只能一次賦值以後值不能被修改(常量)。

24、數據類型之間的轉換:

1)如何將字符串轉換爲基本數據類型?

2)如何將基本數據類型轉換爲字符串?

答:

1)調用基本數據類型對應的包裝類中的方法parseXXX(String)或valueOf(String)即可返回相應基本類型;

2)一種方法是將基本數據類型與空字符串(””)連接(+)即可獲得其所對應的字符串;另一種方法是調用String 類中的valueOf(…)方法返回相應字符串

25、如何實現字符串的反轉及替換?

方法很多,可以自己寫實現也可以使用String或StringBuffer / StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,

26、怎樣將GB2312編碼的字符串轉換爲ISO-8859-1編碼的字符串?

String s1 = "你好";
String s2 = newString(s1.getBytes("GB2312"), "ISO-8859-1");


27、日期和時間:

1)如何取得年月日、小時分鐘秒?

2)如何取得從1970年1月1日0時0分0秒到現在的毫秒數?

3)如何取得某月的最後一天?

4)如何格式化日期?

答:操作方法如下所示:

1)創建java.util.Calendar 實例,調用其get()方法傳入不同的參數即可獲得參數所對應的值

2)以下方法均可獲得該毫秒數:

Calendar.getInstance().getTimeInMillis();  
System.currentTimeMillis();  


3)示例代碼如下:

Calendar time = Calendar.getInstance();  
time.getActualMaximum(Calendar.DAY_OF_MONTH);  


4)利用java.text.DataFormat 的子類(如SimpleDateFormat類)中的format(Date)方法可將日期格式化。

28、打印昨天的當前時刻。

public class YesterdayCurrent {  
    public static void main(String[] args){  
        Calendar cal = Calendar.getInstance();  
        cal.add(Calendar.DATE, -1);  
        System.out.println(cal.getTime());  
    }  
} 


29、比較一下Java 和JavaSciprt。

JavaScript 與Java是兩個公司開發的不同的兩個產品。Java 是原Sun 公司推出的面向對象的程序設計語言,特別適合於互聯網應用程序開發;而JavaScript是Netscape公司的產品,爲了擴展Netscape瀏覽器的功能而開發的一種可以嵌入Web頁面中運行的基於對象和事件驅動的解釋性語言,它的前身是LiveScript;而Java 的前身是Oak語言。

下面對兩種語言間的異同作如下比較:

1)基於對象和麪向對象:Java是一種真正的面向對象的語言,即使是開發簡單的程序,必須設計對象;JavaScript是種腳本語言,它可以用來製作與網絡無關的,與用戶交互作用的複雜軟件。它是一種基於對象(Object-Based)和事件驅動(Event-Driven)的編程語言。因而它本身提供了非常豐富的內部對象供設計人員使用;

2)解釋和編譯:Java 的源代碼在執行之前,必須經過編譯;JavaScript 是一種解釋性編程語言,其源代碼不需經過編譯,由瀏覽器解釋執行;

3)強類型變量和類型弱變量:Java採用強類型變量檢查,即所有變量在編譯之前必須作聲明;JavaScript中變量聲明,採用其弱類型。即變量在使用前不需作聲明,而是解釋器在運行時檢查其數據類型;

4)代碼格式不一樣。

補充:上面列出的四點是原來所謂的標準答案中給出的。其實Java和JavaScript最重要的區別是一個是靜態語言,一個是動態語言。目前的編程語言的發展趨勢是函數式語言和動態語言。在Java中類(class)是一等公民,而JavaScript中函數(function)是一等公民。對於這種問題,在面試時還是用自己的語言回答會更加靠譜。

30、什麼時候用assert?

assertion(斷言)在軟件開發中是一種常用的調試方式,很多開發語言中都支持這種機制。一般來說,assertion用於保證程序最基本、關鍵的正確性。assertion檢查通常在開發和測試時開啓。爲了提高性能,在軟件發佈後, assertion檢查通常是關閉的。在實現中,斷言是一個包含布爾表達式的語句,在執行這個語句時假定該表達式爲true;如果表達式計算爲false,那麼系統會報告一個AssertionError。

斷言用於調試目的:

assert(a > 0); // throws an AssertionError if a <= 0


斷言可以有兩種形式:

assert Expression1;
assert Expression1 : Expression2 ;


Expression1 應該總是產生一個布爾值。

Expression2 可以是得出一個值的任意表達式;這個值用於生成顯示更多調試信息的字符串消息。

斷言在默認情況下是禁用的,要在編譯時啓用斷言,需使用source 1.4 標記:

javac -source 1.4 Test.java

要在運行時啓用斷言,可使用-enableassertions 或者-ea 標記。

要在運行時選擇禁用斷言,可使用-da 或者-disableassertions 標記。

要在系統類中啓用斷言,可使用-esa 或者-dsa 標記。還可以在包的基礎上啓用或者禁用斷言。可以在預計正常情況下不會到達的任何位置上放置斷言。斷言可以用於驗證傳遞給私有方法的參數。不過,斷言不應該用於驗證傳遞給公有方法的參數,因爲不管是否啓用了斷言,公有方法都必須檢查其參數。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試後置條件。另外,斷言不應該以任何方式改變程序的狀態。

31、Error 和Exception 有什麼區別?

Error 表示系統級的錯誤和程序不必處理的異常,是恢復不是不可能但很困難的情況下的一種嚴重問題;比如內存溢出,不可能指望程序能處理這樣的情況;Exception 表示需要捕捉或者需要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示如果程序運行正常,從不會發生的情況。

補充:2005年摩托羅拉的面試中曾經問過這麼一個問題“If a process reports a stack overflow run-time error, what’s the most possible cause?”,給了四個選項a. lack of memory; b. write on an invalid memory space; c. recursive function calling; d. array index out of boundary. Java程序在運行時也可能會遭遇StackOverflowError,這是一個錯誤無法恢復,只能重新修改代碼了,這個面試題的答案是c。如果寫了不能迅速收斂的遞歸,則很有可能引發棧溢出的錯誤,如下所示:

package com.lovo;  
  
public class StackOverflowErrorTest {  
    public static void main(String[] args) {  
        main(null);  
    }  
}


因此,用遞歸編寫程序時一定要牢記兩點:1. 遞歸公式;2. 收斂條件(什麼時候就不再遞歸而是回溯了)。

32、詳解a++和++a的區別

a++ 和 ++a的相同點都是給a+1,不同點是a++是先參加程序的運行再+1,而++a則是先+1再參加程序的運行。
int a=1 b=(a++) +( ++a);b=4;a++先算自身再加1,所以這一步相當於是1,然後變成2
++a先自加再運算,相當於2+1=3,於是b=1+3=4

33、a+=b 和a=a+b的區別

在Java語言中a+=b和a=a+b是有區別的,主要的區別是在運算時精度的問題。
這兩種形式的主要區別在於是否進行數據類型的自動轉換,當兩個操作數同類型時這兩種形式的運算結果是沒有差別的,當兩個操作數數據類型不同時,且左操作數即保存結果的操作數的數據精度要低,此時這兩種形式纔有區別

34,Java中的泛型是什麼 ? 使用泛型的好處是什麼?

泛型是Java SE 1.5的新特性,泛型的本質是參數化類型,也就是說所操作的數據類型被指定爲一個參數。

好處:

1、類型安全,提供編譯期間的類型檢測

2、前後兼容

3、泛化代碼,代碼可以更多的重複利用

4、性能較高,用GJ(泛型JAVA)編寫的代碼可以爲java編譯器和虛擬機帶來更多的類型信息,這些信息對java程序做進一步優化提供條件。

35,Java的泛型是如何工作的 ? 什麼是類型擦除 ?如何工作?

1、類型檢查:在生成字節碼之前提供類型檢查

2、類型擦除:所有類型參數都用他們的限定類型替換,包括類、變量和方法(類型擦除)

3、如果類型擦除和多態性發生了衝突時,則在子類中生成橋方法解決

4、如果調用泛型方法的返回類型被擦除,則在調用該方法時插入強制類型轉換

類型擦除:

所有類型參數都用他們的限定類型替換:

比如T->Object ? extends BaseClass->BaseClass

如何工作:

泛型是通過類型擦除來實現的,編譯器在編譯時擦除了所有類型相關的信息,所以在運行時不存在任何類型相關的信息。例如 List<String>在運行時僅用一個List來表示。這樣做的目的,是確保能和Java 5之前的版本開發二進制類庫進行兼容。你無法在運行時訪問到類型參數,因爲編譯器已經把泛型類型轉換成了原始類型。根據你對這個泛型問題的回答情況,你會得到一些後續提問,比如爲什麼泛型是由類型擦除來實現的或者給你展示一些會導致編譯器出錯的錯誤泛型代碼。

36,你可以把List<String>傳遞給一個接受List<Object>參數的方法嗎?

對任何一個不太熟悉泛型的人來說,這個Java泛型題目看起來令人疑惑,因爲乍看起來String是一種Object,所以 List<String>應當可以用在需要List<Object>的地方,但是事實並非如此。真這樣做的話會導致編譯錯誤。如果你再深一步考慮,你會發現Java這樣做是有意義的,因爲List<Object>可以存儲任何類型的對象包括String, Integer等等,而List<String>卻只能用來存儲String s。

List<Object> objectList;

List<String> stringList;

objectList = stringList; //compilation error incompatible types


37,如何阻止Java中的類型未檢查的警告?

如果你把泛型和原始類型混合起來使用,例如下列代碼,java 5的javac編譯器會產生類型未檢查的警告,例如

List<String> rawList = newArrayList()


注意: Hello.java使用了未檢查或稱爲不安全的操作;

這種警告可以使用@SuppressWarnings(“unchecked”)註解來屏蔽。

38,Java中List<Object>和原始類型List之間的區別?

原始類型和帶參數類型<Object>之間的主要區別是,在編譯時編譯器不會對原始類型進行類型安全檢查,卻會對帶參數的類型進行檢查,通過使用Object作爲類型,可以告知編譯器該方法可以接受任何類型的對象,比如String或Integer。

這道題的考察點在於對泛型中原始類型的正確理解。它們之間的第二點區別是,你可以把任何帶參數的類型傳遞給原始類型List,但卻不能把List<String>傳遞給接受 List<Object>的方法,因爲會產生編譯錯誤。

39,編寫一段泛型程序來實現LRU緩存?

對於喜歡Java編程的人來說這相當於是一次練習。給你個提示,LinkedHashMap可以用來實現固定大小的LRU緩存,當LRU緩存已經滿了的時候,它會把最老的鍵值對移出緩存。

LinkedHashMap提供了一個稱爲removeEldestEntry()的方法,該方法會被put() 和putAll()調用來刪除最老的鍵值對。當然,如果你已經編寫了一個可運行的JUnit測試,你也可以隨意編寫你自己的實現代碼。

40,Array中可以用泛型嗎?

這可能是Java泛型面試題中最簡單的一個了,當然前提是你要知道Array事實上並不支持泛型,這也是爲什麼Joshua Bloch在Effective Java一書中建議使用List來代替Array,因爲List可以提供編譯期的類型安全保證,而Array卻不能。

41,如何編寫一個泛型方法,讓它能接受泛型參數並返回泛型類型?

編寫泛型方法並不困難,你需要用泛型類型來替代原始類型,比如使用T, E or K,V等被廣泛認可的類型佔位符。最簡單的情況下,一個泛型方法可能會像這樣:

  public V put(K key, V value) {

   return cahe.put(key,value);

}


42,C++模板和java泛型之間有何不同?

java泛型實現根植於“類型消除”這一概念。當源代碼被轉換爲Java虛擬機字節碼時,這種技術會消除參數化類型。有了Java泛型,我們可以做的事情也並沒有真正改變多少;他只是讓代碼變得漂亮些。鑑於此,Java泛型有時也被稱爲“語法糖”。

這和 C++模板截然不同。在 C++中,模板本質上就是一套宏指令集,只是換了個名頭,編譯器會針對每種類型創建一份模板代碼的副本。

由於架構設計上的差異,Java泛型和C++模板有很多不同點:

C++模板可以使用int等基本數據類型。Java則不行,必須轉而使用Integer。

在Java中,可以將模板的參數類型限定爲某種特定類型。

在C++中,類型參數可以實例化,但java不支持。

在Java中,類型參數不能用於靜態方法(?)和變量,因爲它們會被不同類型參數指定的實例共享。在C++,這些類時不同的,因此類型參數可以用於靜態方法和靜態變量。

在Java中,不管類型參數是什麼,所有的實例變量都是同一類型。類型參數會在運行時被抹去。在C++中,類型參數不同,實例變量也不同。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章