以下是自己總結的一些Java常見的基礎知識題,答案僅供參考,如有異議請指出。一直保持更新狀態。
1.什么是Java虛擬機?為什么Java被稱作是“平臺無關的編程語言”?
Java虛擬機是一個可以執行Java字節碼的虛擬機進程。Java源文件被編譯成能被Java虛擬機執行的字節碼文件。
2.“static”關鍵字是什么意思?Java中是否可以覆蓋(override)一個private或者是static的方法?
“static”關鍵字表明一個成員變量或者是成員方法可以在沒有所屬的類的實例變量的情況下被訪問。
Java中static方法不能被覆蓋,因為方法覆蓋是基于運行時動態綁定的,而static方法是編譯時靜態綁定的。static方法跟類的任何實例都不相關,所以概念上不適用。
3.是否可以在static環境中訪問非static變量?
static變量在Java中是屬于類的,它在所有的實例中的值是一樣的。當類被Java虛擬機載入的時候,會對static變量進行初始化。如果你的代碼嘗試不用實例來訪問非static的變量,編譯器會報錯,因為這些變量還沒有被創建出來,還沒有跟任何實例關聯上。
4.Java支持的數據類型有哪些?什么是自動拆裝箱?
Java語言支持的8中基本數據類型是:
? byte
? short
? int
? long
? float
? double
? boolean
? char
自動裝箱是Java編譯器在基本數據類型和對應的對象包裝類型之間做的一個轉化。比如:把int轉化成Integer,double轉化成double,等等。反之就是自動拆箱。
5.Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?
方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載O verloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫(Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被”屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。
6.Java支持多繼承么?
不支持,Java不支持多繼承。每個類都只能繼承一個類,但是可以實現多個接口。
7.接口和抽象類的區別是什么?
Java提供和支持創建抽象類和接口。它們的實現有共同點,不同點在于:
? 接口中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
? 類可以實現很多個接口,但是只能繼承一個抽象類
? 類如果要實現一個接口,它必須要實現接口聲明的所有方法。但是,類可以不實現抽象類聲明的所有方法,當然,在這種情況下,類也必須得聲明成是抽象的。
? 抽象類可以在不提供接口方法實現的情況下實現接口。
? Java接口中聲明的變量默認都是final的。抽象類可以包含非final的變量。
? Java接口中的成員函數默認是public的。抽象類的成員函數可以是private,protected或者是public。
? 接口是絕對抽象的,不可以被實例化。抽象類也不可以被實例化,但是,如果它包含main方法的話是可以被調用的。
也可以參考JDK8中抽象類和接口的區別
8.什么是值傳遞和引用傳遞?
對象被值傳遞,意味著傳遞了對象的一個副本。因此,就算是改變了對象副本,也不會影響源對象的值。
對象被引用傳遞,意味著傳遞的并不是實際的對象,而是對象的引用。因此,外部對引用對象所做的改變會反映到所有的對象上。
9.創建線程有幾種不同的方式?你喜歡哪一種?為什么?
有三種方式可以用來創建線程:
? 繼承Thread類
? 實現Runnable接口
? 應用程序可以使用Executor框架來創建線程池
實現Runnable接口這種方式更受歡迎,因為這不需要繼承Thread類。在應用設計中已經繼承了別的對象的情況下,這需要多繼承(而Java不支持多繼承),只能實現接口。同時,線程池也是非常高效的,很容易實現和使用。
10.同步方法和同步代碼塊的區別是什么?
在Java語言中,每一個對象有一把鎖。線程可以使用synchronized關鍵字來獲取對象上的鎖。synchronized關鍵字可應用在方法級別(粗粒度鎖:這里的鎖對象可以是This)或者是代碼塊級別(細粒度鎖:這里的鎖對象就是任意對象)。
11.什么是死鎖(deadlock)?
兩個進程都在等待對方執行完畢才能繼續往下執行的時候就發生了死鎖。結果就是兩個進程都陷入了無限的等待中。
代碼表示:
代碼描述:
public class DieLockDemo {
public static void main(String[] args) {
DieLock dl1 = new DieLock(true);
DieLock dl2 = new DieLock(false);dl1.start();
dl2.start();
}
}
*...理想狀態下dl1線程為true從if執行先打出"if objA"然后再接著打出"if objB"之后釋放A、B的鎖對象,之后dl2線程執行else語句打出"else objB","else objA"。
非理想狀態下dl1先打出"if objA",之后線程dl2執行打出"else objB",然后1、2線程的鎖對象A和B都處于被鎖的狀態,兩個線程爭奪鎖對象發生死鎖現象。..*
public class DieLock extends Thread {
private boolean flag;
public DieLock(boolean flag) {
this.flag = flag;
}
@Override
public void run() {
if (flag) {
synchronized (MyLock.objA) {
System.out.println("if objA");
synchronized (MyLock.objB) {
System.out.println("if objB");
}
}
} else {
synchronized (MyLock.objB) {
System.out.println("else objB");
synchronized (MyLock.objA) {
System.out.println("else objA");
}
}
}
}
}
12.如何確保N個線程可以訪問N個資源同時又不導致死鎖?
使用多線程的時候,一種非常簡單的避免死鎖的方式就是:指定獲取鎖的順序,并強制線程按照指定的順序獲取鎖。因此,如果所有的線程都是以同樣的順序加鎖和釋放鎖,就不會出現死鎖了。
13.Java集合類框架的基本接口有哪些?
Java集合類提供了一套設計良好的支持對一組對象進行操作的接口和類。Java集合類里面最基本的接口有:
? Collection:代表一組對象,每一個對象都是它的子元素。
? Set:不包含重復元素的Collection。
? List:有順序的collection,并且可以包含重復元素。
? Map:可以把鍵(key)映射到值(value)的對象,鍵不能重復。
14.什么是迭代器(Iterator)?
Iterator接口提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器實例的迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。
15.Iterator和ListIterator的區別是什么?
下面列出了他們的區別:
? Iterator可用來遍歷Set和List集合,但是ListIterator只能用來遍歷List。
? Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以后向。
? ListIterator實現了Iterator接口,并包含其他的功能,比如:增加元素,替換元素,獲取前一個和后一個元素的索引,等等。
16.Java中的HashMap的工作原理是什么?
Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。HashMap需要一個hash函數,它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當調用put()方法的時候,HashMap會計算key的hash值,然后把鍵值對存儲在集合中合適的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。
17.HashMap和Hashtable有什么區別?
? HashMap和Hashtable都實現了Map接口,因此很多特性非常相似。但是,他們有以下不同點:
? HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。
? Hashtable是同步的,而HashMap不是。因此,HashMap更適合于單線程環境,而Hashtable適合于多線程環境。
? HashMap提供了可供應用迭代的鍵的集合,因此,HashMap是快速失敗的。另一方面,Hashtable提供了對鍵的列舉(Enumeration)。
o 一般認為Hashtable是一個遺留的類。
18.數組(Array)和列表(ArrayList)有什么區別?什么時候應該使用Array而不是ArrayList?
下面列出了Array和ArrayList的不同點:
? Array可以包含基本類型和對象類型,ArrayList只能包含對象類型。
? Array大小是固定的,ArrayList的大小是動態變化的。
? ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
? 對于基本類型數據,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本數據類型的時候,這種方式相對比較慢。
19.ArrayList和LinkedList有什么區別?
ArrayList和LinkedList都實現了List接口,他們有以下的不同點:
? ArrayList是基于索引的數據接口**,它的底層是數組**。它可以以O(1)時間復雜度對元素進行隨機訪問。與此對應,LinkedList是以元素鏈表的形式存儲它的數據,每一個元素都和它的前一個和后一個元素鏈接在一起,在這種情況下,查找某個元素的時間復雜度是O(n)。
? 相對于ArrayList,LinkedList的插入,添加,刪除操作速度更快,因為當元素被添加到集合任意位置的時候,不需要像數組那樣重新計算大小或者是更新索引。
? LinkedList比ArrayList更占內存,因為LinkedList為每一個節點存儲了兩個引用,一個指向前一個元素,一個指向下一個元素。
也可以參考ArrayList vs. LinkedList。
20.如何權衡是使用無序的數組還是有序的數組?
有序數組最大的好處在于查找的時間復雜度是O(log n),而無序數組是O(n)。有序數組的缺點是插入操作的時間復雜度是O(n),因為值大的元素需要往后移動來給新元素騰位置。相反,無序數組的插入時間復雜度是常量O(1)。
21.HashSet和TreeSet有什么區別?
HashSet是由一個hash表來實現的,因此,它的元素是無序的。add(),remove(),contains()方法的時間復雜度是O(1)。
另一方面,**TreeSet是由一個樹形的結構來實現的,它里面的元素是有序的。**因此,add(),remove(),contains()方法的時間復雜度是O(logn)。
22.Java中垃圾回收有什么目的?什么時候進行垃圾回收?
垃圾回收的目的是識別并且丟棄應用不再使用的對象來釋放和重用資源。
23.如果對象的引用被置為null,垃圾收集器是否會立即釋放對象占用的內存?
不會,在下一個垃圾回收周期中,這個對象將是可被回收的。
24、String是最基本的數據類型嗎?
基本數據類型包括byte、int、char、long、float、double、boolean和short。
java.lang.String類是final類型的,因此不可以繼承這個類、不能修改這個類。為了提高效率節省空間,我們應該用StringBuffer類
25、int 和 Integer 有什么區別
Java 提供兩種不同的類型:引用類型和原始類型(或內置類型)。Int是java的原始數據類型,Integer是java為int提供的封裝類。Java為每個原始類型提供了封裝類。
26、String 和StringBuffer的區別
JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數據。這個String類提供了數值不可改變的字符串。而這個StringBuffer類提供的字符串進行修改。
27、說出ArrayList,Vector, LinkedList的存儲性能和特性
ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大于實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector由于使用了synchronized方法(線程安全),通常性能上較ArrayList差,而 Linke dList使用雙向鏈表實現存儲,按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。
List的子類特點ArrayList:底層數據結構是數組,查詢快,增刪慢線程不安全,效率高Vector:底層數據結構是數組,查詢快,增刪慢線程安全,效率低LinkedList:底層數據結構是鏈表,查詢慢,增刪快線程不安全,效率高
28、Collection 和 Collections的區別
Collection是集合類的上級接口,繼承與他的接口主要有Set 和List.
Collections是針對集合類的一個幫助類,他提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
集合的繼承體系:
29、&和&&的區別。
&是位運算符,表示按位與運算,&&是邏輯運算符,表示邏輯與(and)。
30、final, finally, finalize的區別。
final
用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally是異常處理語句結構的一部分,表示總是執行。
finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關閉文件等。
31、sleep() 和 wait() 有什么區別?
sleep是線程類(Thread)的方法,導致此線程暫停執行指定時間,給執行機會給其他線程,但是監控狀態依然保持,到時后會自動恢復。調用sleep不會釋放對象鎖。
wait是Object類的方法,對此對象調用wait方法導致本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或not ifyAll)后本線程才進入對象鎖定池準備獲得對象鎖進入運行狀態。
32、error和exception有什么區別?
error
表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
exception
表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。
33、同步和異步有何異同,在什么情況下分別使用他們?舉例說明。
如果數據將在線程間共享。例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就是共享數據,必須進行同步存取。
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,并且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。
34、GC是什么? 為什么要有GC?
GC是垃圾收集的意思(Gabage Collection),內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操作方法。
35、short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 +=
1;有什么錯?
short s1 = 1; s1 = s1 + 1;
(s1+1運算結果是int型,需要強制轉換類型)
short s1 = 1; s1 += 1;(可以正確編譯,+=內置運算符運算時可自動變換數據類型)
36、Math.round(11.5)等於多少? Math.round(-11.5)等於多少?
Math.round(11.5)12
Math.round(-11.5)-11
round方法返回與參數最接近的長整數,參數加1/2后求其floor.
37、String s = new String(“xyz”);創建了幾個String Object?
兩個,一個是在堆中創建的s一個是在字符串常量池中創建的“xyz”。
38、接口是否可繼承接口?
抽象類是否可實現(implements)接口?
抽象類是否可繼承實體類(concrete class)?
接口可以繼承接口。抽象類可以實現(implements)接口,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數。
39、List, Set, Map是否繼承自Collection接口?
List,Set是,Map不是
40、abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?
都不能
41、是否可以繼承String類?
String類是final類故不可以繼承。
42、swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
switch(expr1)中,expr1是一個整數表達式。因此傳遞給switch 和 case 語句的參數應該是 int、 short、 char 或者byte。long,string 都不能作用于swtich(1.7版本之后switch語句支持string類型)。
43、try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后?
會執行,在return前執行(finally中程序一定會被執行,return結束后程序結束,所以肯定在之前執行)。
44、兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
不對,有相同的hash code。(hashcode內部也是根據對象的 來做處理的)
45、當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法?
不能,當一個線程進入一個對象的synchronized方法后,其他線程可以進入此對象的非synchronized方法,不能進入synchronized方法,都是同一鎖(同步代碼塊時對象鎖可以是任何對象,同步方法時對象鎖只能是this對象所以無法訪問其他方法)
46、編程題: 寫一個Singleton出來。
Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。
一般Singleton模式通常有幾種種形式:
第一種形式:
定義一個類,它的構造函數為private的,它有一個static的private的該類變量,在類初始化時實例話,通過一個public的getInsta nce方法獲取對它的引用,繼而調用其中的方法。
public class Singleton {
private Singleton(){}
//在自己內部定義自己一個實例,是不是很奇怪?
//注意這是private 只供內部調用
private static Singleton instance = new Singleton();
//這里提供了一個供外部訪問本class的靜態方法,可以直接訪問
public static Singleton getInstance() {
return instance;
}
}
第二種形式:
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance() {
//這個方法比上面有所改進,不用每次都進行生成對象,只是第一次
//使用時生成實例,提高了效率!
if (instance==null)
instance=new Singleton();
return instance; }
}
其他形式:
定義一個類,它的構造函數為private的,所有方法為static的。
一般認為第一種形式要更加安全些
47、Java的接口和C++的虛類的相同和不同處。
由于Java不支持多繼承,而有可能某個類或對象要使用分別在幾個類或對象里面的方法或屬性,現有的單繼承機制就不能滿足要求。與繼承相比,接口有更高的靈活性,因為接口中沒有任何實現代碼。當一個類實現了接口以后,該類要實現接口里面所有的方法和屬性,并且接口里面的屬性在默認狀態下面都是public static,所有方法默認情況下是public.一個類可以實現多個接口。
48、Java中的異常處理機制的簡單原理和應用。
當JAVA 程序違反了JAVA的語義規則時,JAVA虛擬機就會將發生的錯誤表示為一個異常。違反語義規則包括2種情況。一種是JAVA類庫內置的語義檢查。例如數組下標越界,會引發IndexOutOfBoundsException;訪問null的對象時會引發NullPointerException。另一種情況就是JAVA允許程序員擴展這種語義檢查,程序員可以創建自己的異常,并自由選擇在何時用throw關鍵字引發異常。所有的異常都是java.lang.Thowable的子類。
49、垃圾回收的優點和原理。并考慮2種回收機制。
Java語言中一個顯著的特點就是引入了垃圾回收機制,使c++程序員最頭疼的內存管理的問題迎刃而解,它使得Java程序員在編寫程序的時候不再需要考慮內存管理。由于有個垃圾回收機制,Java中的對象不再有”作用域”的概念,只有對象的引用才有”作用域”。垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低級別的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清楚和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。回收機制有分代復制垃圾回收和標記垃圾回收,增量垃圾回收。
50、char型變量中能不能存貯一個中文漢字?為什么?
能夠定義成為一個中文的,因為java中以unicode編碼,一個char占2個字節,所以放一個中文是沒問題的
51、多線程有幾種實現方法,都是什么?同步有幾種實現方法,都是什么?
多線程有兩種實現方法,分別是繼承Thread類與實現Runnable接口
同步的實現方面有兩種,分別是同步代碼塊和同步方法
52、線程的基本概念、線程的基本狀態以及狀態之間的關系
線程指在程序執行過程中,能夠執行程序代碼的一個執行單位,每個程序至少都有一個線程,也就是程序本身。
Java中的線程有五種狀態分別是:新建、就緒、運行、阻塞、結束。
53、簡述synchronized和java.util.concurrent.locks.Lock的異同?
主要相同點:Lock能完成synchronized所實現的所有功能
主要不同點:Lock有比synchronized更精確的線程語義和更好的性能。
Lock是一個類,synchronized是一個關鍵字
synchronized會自動釋放鎖,而Lock一定要求程序員手工釋放,并且必須在finally從句中釋放。
54、JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什么意義?在try塊中可以拋出異常嗎?
Java 通過面向對象的方法進行異常處理,把各種不同的異常進行分類,并提供了良好的接口。在Java中,每個異常都是一個對象,它是Throwable 類或其它子類的實例。當一個方法出現異常后便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法可以捕獲到這個異常并進行處理。Java的異常處理是通過5 個關鍵詞來實現的:try、catch、throw、throws和finally。一般情況下是用try來執行一段程序,如果出現異常,系統會拋出(throws)一個異常,這時候你可以通過它的類型來捕捉(catch)它,或最后(finally)由缺省處理器來處理。
用try來指定一塊預防所有”異常”的程序。緊跟在try程序后面,應包含一個catch子句來指定你想要捕捉的”異常”的類型。
throw語句用來明確地拋出一個”異常”。
throws用來標明一個成員函數可能拋出的各種”異常”。
Finally為確保一段代碼不管發生什么”異常”都被執行一段代碼。
可以在一個成員函數調用的外面寫一個try語句,在這個成員函數內部寫另一個try語句保護其他代碼。每當遇到一個try語句,”異常”的框架就放到堆棧上面,直到所有的try語句都完成。如果下一級的try語句沒有對某種”異常”進行處理,堆棧就會展開,直到遇到有處理這種”異常”的try語句。
55、一個”.java“源文件中是否可以包括多個類(不是內部類)?有什么限制?
可以。必須只有一個類名與文件名相同。
56、java中有幾種類型的流?JDK為每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類?
字節流,字符流。字節流繼承于InputStream \ OutputStream,字符流繼承于InputStreamReader \ OutputStreamWriter。在java.io包中還有許多其他的流,主要是為了提高性能和使用方便。
57、java中會存在內存泄漏嗎,請簡單描述。
會。如:int i,i2; return (i-i2); //when i為足夠大的正數,i2為足夠大的負數。結果會造成溢位,導致錯誤。
58、java中實現多態的機制是什么?
方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。
59、垃圾回收器的基本原理是什么?垃圾回收器可以馬上回收內存嗎?有什么辦法主動通知虛擬機進行垃圾回收?
對于GC來說,當程序員創建對象時,GC就開始監控這個對象的地址、大小以及使用情況。通常,GC采用有向圖的方式記錄和管理堆(heap)中的所有對象。通過這種方式確定哪些對象是”可達的”,哪些對象是”不可達的”。當GC確定一些對象為”不可達”時,GC就有責任回收這些內存空間。可以。程序員可以手動執行System.gc(),通知GC運行,但是Java語言規范并不保證GC一定會執行。
60、什么是java序列化,如何實現java序列化?
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸于網絡之間。序列化是為了解決在對對象流進行讀寫操作時所引發的問題。
序列化的實現:將需要被序列化的類實現Serializable接口,該接口沒有需要實現的方法,implements Serializable只是為了標注該對象是可被序列化的,然后使用一個輸出流(如:FileOutputStream)來構造一個ObjectOutputStream(對象流)對象,接著,使用ObjectOutputStream對象的writeObject(Object obj)方法就可以將參數為obj的對象寫出(即保存其狀態),要恢復的話則用輸入流。
61、是否可以從一個static方法內部發出對非static方法的調用?
不可以,如果其中包含對象的method();不能保證對象初始化.
62、List、Map、Set三個接口,存取元素時,各有什么特點?
List 以特定次序來持有元素,可有重復元素。
Set 無法擁有重復元素,內部排序。
Map 保存key-value值,value可多值。
63、使用final關鍵字修飾一個變量時,是引用不能變,還是引用的對象不能變?
使用final關鍵字修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容還是可以改變的。例如,對于如下語句:
final StringBuffer a=new StringBuffer(“immutable”);
執行如下語句將報告編譯期錯誤:
a=new StringBuffer("");
但是,執行如下語句則可以通過編譯:
a.append(" broken!");
有人在定義方法的參數時,可能想采用如下形式來阻止方法內部修改傳進來的參數對象:
public void method(final StringBuffer param)
{
}
實際上,這是辦不到的,在該方法內部仍然可以增加如下代碼來修改參數對象:
param.append(“a”);
65、請說出作用域public,private,protected,以及不寫時的區別
這四個作用域的可見范圍如下表所示。
說明:如果在修飾的元素上面沒有寫任何訪問修飾符,則表示friendly。
作用域 當前類 同一package 子孫類 其他package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
備注:只要記住了有4種訪問權限,4個訪問范圍,然后將全選和范圍在水平和垂直方向上分別按排從小到大或從大到小的順序排列,就很容易畫出上面的圖了。
66、線程如何同步和通訊。
線程同步
什么是線程同步?
當使用多個線程來訪問同一個數據時,非常容易出現線程安全問題(比如多個線程都在操作同一數據導致數據不一致),所以我們用同步機制來解決這些問題。
實現同步機制有兩個方法:
1。同步代碼塊:
synchronized(同一個數據){} 同一個數據:就是N條線程同時訪問一個數據。
2。同步方法:
public synchronized 數據返回類型 方法名(){}
就是使用 synchronized 來修飾某個方法,則該方法稱為同步方法。對于同步方法而言,無需顯示指定同步監視器,同步方法的同步監視器是 this 也就是該對象的本身(這里指的對象本身有點含糊,其實就是調用該同步方法的對象)通過使用同步方法,可非常方便的將某類變成線程安全的類
線程通訊:
為什么要使用線程通訊?
當使用synchronized 來修飾某個共享資源時(分同步代碼塊和同步方法兩種情況),當某個線程獲得共享資源的鎖后就可以執行相應的代碼段,直到該線程運行完該代碼段后才釋放對該 共享資源的鎖,讓其他線程有機會執行對該共享資源的修改。當某個線程占有某個共享資源的鎖時,如果另外一個線程也想獲得這把鎖運行就需要使用wait() 和notify()/notifyAll()方法來進行線程通訊了。
其他答案:
同學回答說synchronized方法或代碼塊!面試官似乎不太滿意!
只有多個synchronized代碼塊使用的是同一個監視器對象,這些synchronized代碼塊之間才具有線程互斥的效果,假如a代碼塊用obj1作為監視器對象,假如b代碼塊用obj2作為監視器對象,那么,兩個并發的線程可以同時分別進入這兩個代碼塊中。 …這里還可以分析一下同步的原理。
對于同步方法的分析,所用的同步監視器對象是this
接著對于靜態同步方法的分析,所用的同步監視器對象是該類的Class對象
接著對如何實現代碼塊與方法的同步進行分析。
67、String s = “Hello”;s = s + " world!";這兩行代碼執行后,原始的String對象中的內容到底變了沒有?
沒有。因為String被設計成不可變(immutable)類,所以它的所有對象都是不可變對象。在這段代碼中,s原先指向一個String對象,內容是 “Hello”,然后我們對s進行了+操作,那么s所指向的那個對象是否發生了改變呢?答案是沒有。這時,s不指向原來那個對象了,而指向了另一個 String對象,內容為"Hello world!",原來那個對象還存在于內存之中,只是s這個引用變量不再指向它了。
68、String 和StringBuffer的區別
JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字符串,即包含多個字符的字符數據。String類表示內容不可改變的字符串。而StringBuffer類表示內容可以被修改的字符串。當你知道字符數據要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字符數據。另外,String實現了equals方法,new String(“abc”).equals(new String(“abc”)的結果為true,而StringBuffer沒有實現equals方法,所以,new StringBuffer(“abc”).equals(new StringBuffer(“abc”)的結果為false。
69、StringBuffer與StringBuilder的區別
StringBuffer和StringBuilder類都表示內容可以被修改的字符串,**StringBuilder是線程不安全的,運行效率高,**如果一個字符串變量是在方法里面定義,這種情況只可能有一個線程訪問它,不存在不安全的因素了,則用StringBuilder。如果要在類里面定義成員變量,并且這個類的實例對象會在多線程環境下使用,那么最好用StringBuffer。
70、數組有沒有length()這個方法? String有沒有length()這個方法?
數組沒有length()這個方法,有length的屬性。String有有length()這個方法。
71、下面的程序代碼輸出的結果是多少?
public class smallT
{public static void main(String args[]){smallT t = new smallT();int b = t.get();System.out.println(b);}public int get(){try{return 1 ;}finally{return 2 ;}}
}返回的結果是2。
72、設計4個線程,其中兩個線程每次對j增加1,另外兩個線程對j每次減少1。寫出程序。
以下程序使用內部類實現線程,對j增減的時候沒有考慮順序問題。
public class ThreadTest1
{
private int j;
public static void main(String args[]){ ThreadTest1 tt=new ThreadTest1(); Inc inc=tt.new Inc(); Dec dec=tt.new Dec(); for(int i=0;i<2;i++){ Thread t=new Thread(inc); t.start(); t=new Thread(dec); t.start(); } }
private synchronized void inc(){ j++; System.out.println(Thread.currentThread().getName()+"-inc:"+j); }
private synchronized void dec(){ j--; System.out.println(Thread.currentThread().getName()+"-dec:"+j); }
class Inc implements Runnable{ public void run(){ for(int i=0;i<100;i++){ inc(); } }
}
class Dec implements Runnable{ public void run(){ for(int i=0;i<100;i++){ dec(); }
73、heap和stack有什么區別。
java的內存分為兩類,一類是棧內存,一類是堆內存。棧內存是指程序進入一個方法時,會為這個方法單獨分配一塊私屬存儲空間,用于存儲這個方法內部的局部變量,當這個方法結束時,分配給這個方法的棧會釋放,這個棧中的變量也將隨之釋放。
堆是與棧作用不同的內存,一般用于存放不放在當前方法棧中的那些數據,例如,使用new創建的對象都放在堆里,所以,它不會隨方法的結束而消失。方法中的局部變量使用final修飾后,放在堆中,而不是棧中。
74、寫一單實例類要求精簡、清晰。
懶漢模式:
public class SingletonDemo {private static SingletonDemo instance;private SingletonDemo(){}public static SingletonDemo getInstance(){if(instance==null){instance=new SingletonDemo();}return instance;}
}
#如上,通過提供一個靜態的對象instance,利用private權限的構造方法和getInstance()方法來給予訪問者一個單例。
75、一列數的規則如下: 1、1、2、3、5、8、13、21、34… 求第30位數是多少, 用遞歸算法實現
public class Test { public static void main(String[] args) { System.out.println("結果是:"+Test.foo(30)); } /** * 遞歸算法實現 */ public static int foo(int i){ if(i<=0) return 0; else if(i>0 && i<=2) return 1; return foo(i-1) + foo(i-2); }
}
76、
/*面試題:final修飾局部變量的問題基本類型:基本類型的值不能發生改變。引用類型:引用類型的地址值不能發生改變,但是,該對象的堆內存的值是可以改變的。結果:10010--------------10100--------------10100
*/
class Student {int age = 10;
}class FinalTest {public static void main(String[] args) {//局部變量是基本數據類型int x = 10;x = 100;System.out.println(x);final int y = 10;//無法為最終變量y分配值//y = 100;System.out.println(y);System.out.println("--------------");//局部變量是引用數據類型Student s = new Student();System.out.println(s.age);s.age = 100;System.out.println(s.age);System.out.println("--------------");final Student ss = new Student();System.out.println(ss.age);ss.age = 100;System.out.println(ss.age);//重新分配內存空間//無法為最終變量ss分配值ss = new Student();}
}
77、多態中成員訪問的特點
/*多態:同一個對象(事物),在不同時刻體現出來的不同狀態。舉例:貓是貓,貓是動物。水(液體,固體,氣態)。多態的前提:A:要有繼承關系。B:要有方法重寫。其實沒有也是可以的,但是如果沒有這個就沒有意義。動物 d = new 貓();//讀的時候從右往左讀(也可以這樣理解貓是new出來的對象,而左邊是一個類。所以就相當于判斷一個對象是不是這個類的實例)貓是貓,貓是動物。d.show();動物 d = new 狗();d.show();C:要有父類引用指向子類對象。父 f = new 子();用代碼體現一下多態。多態中的成員訪問特點:A:成員變量編譯看左邊,運行看左邊。B:構造方法創建子類對象的時候,訪問父類的構造方法,對父類的數據進行初始化。C:成員方法編譯看左邊,運行看右邊。D:靜態方法編譯看左邊,運行看左邊。(靜態和類相關,算不上重寫,所以,訪問還是左邊的)由于成員方法存在方法重寫,所以它運行看右邊。
*/
class Fu {public int num = 100;public void show() {System.out.println("show Fu");}public static void function() {System.out.println("function Fu");}
}class Zi extends Fu {public int num = 1000;public int num2 = 200;public void show() {System.out.println("show Zi");}public void method() {System.out.println("method zi");}public static void function() {System.out.println("function Zi");}
}class DuoTaiDemo {public static void main(String[] args) {//要有父類引用指向子類對象。//父 f = new 子();Fu f = new Zi();System.out.println(f.num);//找不到符號//System.out.println(f.num2);f.show();//找不到符號//f.method();f.function();}
}