這是一份Java基礎知識的面試題。在網上的關於Java的面試題數不勝數,但認真看過感受大多數都沒有實用性,有不少是面試官根本就不會問到的,那些已經脫離了實際開發的技術問題。而這份資料來源自一份我的以爲最貼近真實面試的Java面試題,網上流傳較少。java
最近又對這份Java基礎面試題從新整理了一遍,本人從新編輯後結合了本身許屢次的面試經歷和經驗,作出了標記,劃分了重點,以及對某些知識作出一些簡單明白的註釋,相信能夠對須要回顧Java知識,以及準備着面試的Java開發工程師會有必定幫助。c++
1. 面向對象的特徵有哪些方面?程序員
答:web
1. 繼承面試
經過繼承容許複用已有的類。繼承關係是一種通常到特殊的關係,好比蘋果類繼承水果類,這個過程稱爲類繼承。算法
子類能夠從父類那裏繼承獲得方法和成員變量,並且子類能夠修改或增長新的方法使之適合子類的須要。sql
2. 封裝編程
封裝是把對象的狀態數據隱藏起來,再經過暴露合適的方法來容許外部程序修改對象的狀態數據。Java的封裝主要經過private,protected,public等訪問控制符來實現。bootstrap
3. 多態設計模式
多態指的是同一個類型的引用類型的變量在執行相同的方法時,實際上會呈現出多種不一樣的行爲特徵。
多態增長了編程的靈活性,實際上大量設計模式都是基於多態類實現的。
4. 抽象
抽象就是忽略與當前目標無關的方面,以便更充分的突出與當前目標有關的方面。
抽象包括兩個方面,一是過程抽象,二是數據抽象。
2. Java中實現多態的機制是什麼?
答:Java容許父類或接口定義的引用變量指向子類或具體實現類的實例對象,
(致使編譯時引用變量指向的方法和程序在內存裏運行時實例對象調用的方法不一致。)
而程序調用的方法在運行時才動態綁定,就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
3. 一個.java源文件中是否能夠包括多個類(不是內部類)?有什麼限制?
答:能夠有多個類,可是隻能有一個有public修飾的類,而且public類的類名必須與文件名相同。包含多個類的.java源文件編譯以後會產生多個.class文件。
4. String是最基本的數據類型嗎?
答:不是。
最基本的數據類型有:byte,short,int,long,char,float,double,Boolean
String是java.lang.String 類,屬於引用類型。
(所謂的引用類型包括:類,接口,數組。
由於String是final修飾的類,是不可繼承的類。而且是一個不可變類。所以若是程序須要使用的字符串所包含的字符序列須要常常改變,建議使用StringBuffer(線程安全,性能略差)類或者StringBuilder(線程不安全,性能好)類。)
5. Java有沒有goto (轉到)?
答:沒有。由於goto是Java的保留字,暫時不是Java的關鍵字。
6. int和Integer有什麼區別?
答:int是Java的基本數據類型,Integer是Java爲int提供的包裝類(封裝類)。Integer包裝類具備面向對象的特徵。
從Java5開始,Java提供了自動裝箱,自動拆箱功能。所以包裝類也能夠直接參與表達式運算,所以使用起來十分方便。
(Java爲每一個原始類型提供了包裝類。
在JSP開發中,Integer的默認值爲null,因此用EL輸出null的Integer時,會顯示空白字符串,而int的默認值爲0,因此int不適合做爲Web層的表單數據的類型。
另外,Integer提供了多個與整數相關的操做方法,例如,將一個字符串轉換成整數,Integer中還定義了表示整數的最大值和最小值的常量。)
7.String和StringBuffer,StringBuilder的區別?
答:
StringBuffer是線程安全的,性能較差,而StringBuilder是線程不安全的,適合單線程環境使用,性能較好。
String表明了字符序列不可變的字符串,而StringBuffer,StringBuilder表明了字符序列可變的字符串。
(它們都是CharSequence(字符序列)的實現類,均可以做爲字符串使用。
)
8.Collection和Collections的區別?
答:Collection是集合類(List集合,Set集合,Queue隊列)的根接口。
Collections是針對集合類的一個工具類,它提供一系列靜態方法實現對各類集合的搜索,排序,線程安全化等操做。
9.說說&和&&的區別?
答:
&和&&均可以用做邏輯與的運算符,&當運算符兩邊的表達式的結果都爲true時,整個運算結果才爲true,不然,只要有一方爲false,則結果爲false。
雙與有短路的功能,也稱短路與。若是第一個表達式爲false,則再也不計算第二個表達式了。實際開發中能夠用來把要比較的表達式放後面,排除報空指針異常的狀況。
而單與在第一個表達式爲false時,還會計算第二個表達式,因此性能略慢。
除此以外,&還能夠用做位運算符,當&操做符兩邊不是boolean類型時,&表示按位與操做。
10.Overload和Override的區別。
Overloaded的方法是否能夠改變返回值的類型?
答:Overload是方法的重載。(load 加載)
Override是方法的重寫,也叫覆蓋。
Overload要求兩個方法具備方法名相同,形參列表不一樣的要求,返回值類型不能做爲重載的條件。
Override要求子類方法與父類方法具備「兩同兩小一大」的要求。
兩同:父類方法,子類方法的方法名,形參列表相同。
兩小:子類方法的返回值類型要麼是父類方法返回值類型的子類,要麼返回值類型相同。
子類方法的拋出異常類型要麼是父類方法拋出異常類型的之類,要麼異常類型相同。
一大:子類的訪問權限要麼比父類的大,要麼相同。
Overloaded方法能夠改變返回值的類型。
11.Java如何跳出當前的多重嵌套循環?
答:能夠在外面的循環語句前定義一個標號,而後在裏層循環體的代碼中使用帶有標號的break語句,便可跳出外層循環。
例如:
Outer:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(「i=」 + i + 「,j=」 + j);
if(j == 5) break Outer;
}
}
12.switch語句(判斷選擇)可否做用在byte上,可否做用在long上,可否做用在String上?
答:在Java1.7之前,能夠做用在char,byte,short,int以及對應的包裝類上。
在Java1.7之後,switch中能夠是字符串類型,因此能夠做用在String上。
也能夠是枚舉類型,在Java1.7之前以及之後都不能做用在long,double,float,boolean以及對應的包裝類上。
(long,double,float,long比較特殊)
13.String s = new String(「xyz」);建立了幾個String Object?
答:兩個。一個是直接量的xyz對象,另外一個是經過new String()構造器建立出來的String對象。一般來講,應該儘可能使用直接量的String對象,這樣具備更好的性能。
直接量就是程序中直接使用的數據值。
14.數組有沒有length()這個方法?String有沒有length()這個方法?
答:數組沒有length()這個方法,只有length這個屬性。String有length()方法。
Length長度。
15.short s1 = 1;s1 = s1 + 1;有什麼錯?short s1 = 1;s1+=s1有什麼錯?
答:s1 + 1 在運算時會自動提高表達式的類型,s1 + 1結果是int型,但複製給short類型的s1時,編譯器將報告須要強制轉換類型的錯誤。
第二個,因爲+=運算符裏已經包括了一個隱式的強制類型轉換,所以它不會有任何錯誤。
16.char型變量中能不能存儲一箇中文字符?爲何?
答:char型變量是用來存儲Unicode編碼的字符的,Unicode編碼字符集中包含了漢字,所以char型變量中能夠存儲漢字。
不過,若是某個特殊漢字沒有被包含在Unicode編碼字符集中,那麼,char型變量中不能存儲這個特殊漢字。
此外,char類型的變量佔兩個字節,而Unicode編碼中每一個字符也佔兩個字節。所以char型變量能夠存儲任何一個Unicode字符。
Unicode又稱統一碼。
17.用最有效率的方法算出2乘以8等於幾?
答:2<<3 ,<<,箭頭向左,是左移運算符,>>,箭頭向右,是右移運算符
由於將一個數左移n位,就至關於乘以了2的n次方;那麼,一個數乘以8只要將其左移3位便可,2的3次方,而CPU直接支持位運算,效率最高。
可是須要注意的是,若是這個數字自己已經很大,好比自己已是2的30次方了,此時再使用這種位移運算就可能致使「溢出」,這樣就得不到正確的結果了。
18.使用final關鍵字修飾一個變量時,是引用不能變,仍是引用的對象不能變?
答:使用final關鍵字修飾一個變量時,是指被修飾的引用變量不能變,引用變量所指向的對象的內容是能夠改變的。
例如,對於以下語句:
final StringBuilder a=new StringBuilder ("immutable");
執行以下語句將報告編譯錯誤:
a = new StringBuilder ("");
但以下語句則是徹底正確的
a.append("fkjava.org");
有人但願在定義方法的形參時,經過final修飾符來阻止方法內部修改傳進來的實參:
public void method(final StringBuilder param)
{
}
實際上這沒有用,在該方法內部仍然能夠增長以下代碼來修改實參對象:
param.append("fkjava.org");
19.」==」和equals方法究竟有什麼區別?
答:通俗地講,」==」比較左右是否是一個東西,equals是比較左右是否是長得同樣。
==操做符的功能有兩個:
A. 若是==的兩邊是基本類型的變量,包裝類對象所組成的表達式,==用於比較兩邊的表達式的值是否相等,若是值相等,即便數據類不一樣,也會返回true。
B. 若是==的兩邊是引用類型的變量,==用於判斷這兩個引用類型的變量是否引用同一塊內存,只有它們引用同一塊內存時,==纔會返回true。
C. 而equals()則是java.lang.Object類的一個方法,所以任何Java對象均可以調用此方法與其它對象進行比較。
D. 開發者重寫equals()方法就能夠根據業務要求來決定這兩個對象是否「相等」。
20.靜態變量和實例變量的區別?
答:A.在語法定義上的區別,靜態變量前要加static關鍵字,而實例變量前則不加。
B.在程序運行時的區別,實例變量屬於一個對象,必須先建立實例對象,它的實例變量纔會被分配空間,才能使用這個實例變量。靜態變量則屬於類,只要程序加載了類的字節碼,不用建立任何實例對象,靜態變量就會被分配空間,靜態變量就能夠被使用了。
總之,實例變量必須建立對象後才能夠經過這個對象來使用,靜態變量則能夠直接使用類名來引用。
C.在內存中,static修飾的類變量只能有一個,而實例變量每建立一個實例對象就能夠分配一個。
21.是否能夠從一個static方法內部調用非static方法?
答:不能夠,靜態成員不能夠調用非靜態成員。
非static方法屬於對象,必須建立一個對象後,才能夠經過該對象來調用實例方法。
而static方法調用時不須要建立對象,經過類就能夠調用該方法。
也就是說,當一個static方法被調用時,可能尚未建立任何實例對象。
所以Java不容許static方法內部調用非static方法。
22.Math.round(11.5)等於多少?Math.round(-11.5)等於多少?
答:Math類中提供了三個與取整有關的方法:ceil,floor,round,這些方法的做用與它們的英文名稱的含義相對應。Ceil:天花板,向上取整Math.ceil(11.3)=12,Math.ceil(-11.3)=-11
Floor:地板,向下取整Math.floor(11.6)的結果爲11,Math.floor(-11.6)=-12
Round:表示「四捨五入」,Math.round(11.5)=12,Math.round(-11.5)=-11。
23.請說出做用域public,private,protected,以及不寫時的區別。
答:這四個做用域的可見範圍以下表所示。
做用域 當前類 同一package 子類 全局
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ √ √ √
若是在修飾的元素上面沒有寫任何訪問修飾符,則表示default。
訪問權限由大到小是:public,protected,default,private
Java存在的4個訪問範圍:全局,子類,同一個package,當前類
24.外部類能用private,protected修飾嗎?內部類能夠用private,protected修飾嗎?
答:外部類不能用private,protected修飾。內部類能用private,protected修飾。
外部類的上一級程序單位是包package,所以它只能有兩個使用範圍:包內和包外,所以它只能使用public(表示能夠在全局位置訪問),和默認修飾符default(表示只能被同一個包內的其它類使用)修飾。
25.一個類定義多個重載方法,參數分別是int,char,和double,而後將double x=2傳遞進去,會選擇哪一個方法?
答:選擇參數類型爲double的方法。
26.說說has a(有)與is a(是)的區別。
答:is a是典型的「通常到特殊「的關係,也就是典型的繼承關係。例如Apple is a Fruit.。蘋果是水果。Apple是一種特殊的Fruit,也就是說Apple繼承了Fruit。
has a是典型的「組合「關係。好比Wolf has a Leg.狼有腿。也就是Leg組合成了Wolf。
須要指出的是:因爲繼承會形成對父類的破壞,所以有時候能夠經過組合來代替繼承。
使用繼承的好處:程序語義更好理解。壞處是:子類可能重寫父類方法,不利於父類封裝。
使用組合則形成語義的混淆,但組合類不會重寫被組合類的方法,所以更利於被複合類封裝。
27.ClassLoader如何加載Class?
答:JVM(Java虛擬機)裏有多個類加載,每一個類加載能夠負責加載特定位置的類。
除了bootstrap以外,其它的類加載器自己也是java類,它們的父類是ClassLoader。
28.Java抽象類的做用。
答:抽象類更利於代碼的維護和重用。
抽象類的特色:1.擁有抽象方法。
2.抽象方法和抽象類都必須被abstract關鍵字修飾。
3.抽象類不能夠建立實例和實例化對象,由於抽象類自己是不完整的。
4.抽象類的抽象方法要被使用,必須由子類重寫全部父類抽象類的抽象方法,創建子類對象調用。(若是子類只重寫(覆蓋)了部分抽象方法,那麼該子類仍是一個抽象類)
抽象類比通常類多了抽象方法。
28.GC是什麼?爲何要有GC?
答:GC是垃圾收集的意思,是Java的垃圾回收機制。
內存處理是編程人員容易出現問題的地方,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的。
Java的System和Runtime類都提供了「通知「程序進行垃圾回收的方法。
JVM什麼時候來進行垃圾回收,仍是由JVM本身來決定。
29垃圾回收的優勢和原理。並考慮2種回收機制。
答:
1.Java語言最顯著的特色就是引入了垃圾回收機制,它使java程序員在編寫程序時再也不考慮內存管理的問題。
2.因爲有垃圾回收機制,Java中的對象再也不有「做用域「的概念,只有引用的對象纔有做用域。
3.垃圾回收機制有效的防止了內存泄漏,能夠有效的使用可以使用的內存。
4.垃圾回收器一般做爲一個單獨的低級別的線程運行,在不可預知的狀況下對內存堆中已經死亡的或很長的時間沒有用過的對象進行清除和回收。
5.程序員不能實時的對某個對象或全部對象調用垃圾回收器進行垃圾回收。
垃圾回收機制有分代複製垃圾回收,標記垃圾回收,增量垃圾回收。
30.垃圾回收器的基本原理是什麼?垃圾回收器能夠立刻回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?
答:對於Java程序中對象而言,若是這個對象沒有任何引用變量引用它,那麼這個對象不能被程序訪問,所以可認爲它是垃圾。
1. 只要有1個以上的引用變量引用該對象,該對象就不會被垃圾回收。
2. 對於Java的垃圾回收器來講,它使用「有向圖「來記錄和管理堆內存中的全部對象,經過這個有向圖就能夠識別哪些對象是」可達的「(有1個引用變量引用該對象),哪些對象是」不可達的「,全部不可達的對象就會被垃圾回收。
3. 程序員能夠手動執行System.gc(),通知GC運行,但這只是一個通知,而JVM依然有權決定什麼時候進行垃圾回收。
31.何時用assert
答:assert是JDK1.4新增的關鍵字。
assertion斷言在軟件開發中是一種常見的調試方式,不少開發語言中都支持這種機制。在實現中,assert就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值爲true,若是該值爲false,說明程序已經處於不正確的狀態下,assert將給出警告或退出。
Java的assert是關鍵字。
Java命令默認不啓動斷言,
爲了啓動用戶斷言,應該在運行java命令時增長-ea(Enable Assert)選項。
爲了啓動系統斷言,應該在運行java命令時增長-esa(Enable System Assert)選項。
32.Java中會存在內存泄漏嗎?請簡單描述。
答:什麼是內存泄漏:程序運行過程當中會不斷地分配空間;那些再也不使用的內存空間應該即時回收它們,從而保證系統能夠再次使用這些內存。若是存在無用的內存沒有被回收回來,那就是內存泄漏。
33.能不能本身寫個類,也叫java.lang.String?
答:能夠,但在應用的時候,須要用本身的類加載器去加載,不然,系統的類加載器永遠只是去加載jre.jar包中的那個java.lang.String。
但在Tomcat的web應用程序中,都是由webapp本身的類加載器先本身加載WEB-INF/classes目錄中的類,而後才委託上級的類加載器加載,若是咱們在Tomcat的web應用程序中寫一個java.lang.String,這時候Servlet程序加載的就是咱們本身寫的java.lang.String。但這樣作就會出不少潛在的問題,原來全部用了java.lang.String類都將出現問題。
34.ArrayList如何實現插入的數據按自定義的方式有序存放?
答:編程思路:實現一個類對ArrayList進行包裝,當程序試圖向ArrayList中放入數據時,程序將先檢查該元素與ArrayList集合中其餘元素的大小,而後將該元素插入到指定位置。
35.序列化接口的id有什麼用?
答:(對象的序列化:把對象轉換爲字節序列的過程.
對象的反序列化:把字節序列恢復爲對象的過程。
對象的序列化主要有兩種用途:
1. 把對象的字節序列永久地保存到硬盤上,一般放在一個文件中。
2. 在網絡上傳送對象的字節序列。
在不少應用中,須要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。)
反序列化Java對象時必須提供該對象的class文件,如今的問題是隨着項目的升級,系統的class文件也會升級,Java如何保證兩個class文件的兼容性?
Java序列化機制容許爲序列化類提供一個UID,也就是說若是一個類升級後,只要它的id值保持不變,序列化機制也會把它們當成同一個序列化版本。
(序列化類的id是爲了在進行項目升級時,保證系統的兩個class文件的兼容性,不會致使重複和衝突。)
36.hashCode()方法的做用?
答:hashCode()方法與equals()方法相似。都容許用戶定義子類重寫這兩個方法。
equals()主要判斷兩個對象表面上或者內容上看是否相同。
而hashCode方法的判斷就要嚴格的多。
若是兩個對象的hashCode()相等,便可認爲這兩個對象是相等的。
所以當咱們重寫一個類的equals()方法時,也應該重寫它的hashCode()方法。並且這兩個方法判斷對象的標準也應該是同樣的。
37.編寫一個函數將十六進制的字符串參數轉換成整數返回。
String str = 「13abf」;
Int len = str.length;
Int sum = 0;
Integer.parseInt(str,16);
parseInt方法提供了把16進制字符串參數轉換成整數返回的方法。
38.銀行還款問題
銀行貸款的還款方式中最經常使用的是一種叫「等額本息」,還款法,即借款人在約定還款期限內的每一期(月)歸還的金額(產生的利息+部分本金)都是相等的,現有一筆總額爲T元的N年期住房貸款,年利率爲R,要求算出每一期的還款的本金和利息總額,請寫出解決思路和任意一種編程語言實現的主要代碼。
思路:既然是按月還款,那我就要將N年按月來計算,即要還N*12個月,這樣就能夠求出每個月要還的本金。因爲每個月要還的那部分本金所欠的時間不一樣,因此,它們所產生的利息是不一樣的,該部分本金的利息爲:部分本金額*所欠月數*月利率。應該是這麼個算法,若是利息還計利息,若是月還款不按年利率來算,老百姓算不明白的。
39.*任意數字序列「123456」之類,輸出它們全部的排列組合
答:String str = "fkjav";
char[] arr1 = str.toCharArray();
char[] arr2 = java.util.Arrays.copyOf(arr1,arr1.length);
for(int i=0;i<arr1.length-1;i++)
{
for(int j = i+1;j<arr2.length;j++){
System.out.println(arr1[i] + "," + arr2[j]);
}
}
40.構造器Constructor是否可被override?
答:構造器Constructor不能被繼承,所以不能重寫Override,但能夠被重載Overrload(形參列表不一樣)。
41.接口是否能夠繼承接口?抽象類是否能夠實現(implements)接口?抽象類是否能夠繼承具體類(concrete class)?抽象類中是否能夠有靜態的main方法?
答:接口能夠繼承接口。
抽象類能夠實現接口。
抽象類能夠繼承具體類。
抽象類中能夠有靜態的main方法。
歸法:抽象類的特徵是有得有失,獲得的功能是抽象類能夠擁有抽象方法(固然也能夠沒有);失去的功能是抽象類不能建立實例了。至於其餘的,抽象類與普通類在語法上大體是同樣的。
(抽象類除了不能建立實例,只要普通類能夠的它均可以。)
42.寫clone()方法時,一般都有一行代碼,是什麼?
答:clone故名思意就是複製,當對象調用此方法,就會在內存中分配一個和源對象一樣大小的空間,在這個空間中建立一個新的複製對象。
clone有缺省(默認)行爲,super.clone();
由於首先要把父類中的成員複製到位,而後纔是複製本身的成員。
43.abstract class 和interface有什麼區別?
答:抽象類和接口的語法區別:
接口能夠說成是抽象類的一種特例,接口中全部方法都必須是抽象的。
1.一個類能夠實現多個接口,但只能繼承一個抽象類。
1.接口是完全的抽象類。抽象類能夠包含非抽象的普通方法,接口中的全部方法必須都是抽象的。
2.抽象類能夠有構造器,接口中不能有構造器。
3.抽象類中能夠有實例成員變量,接口中沒有實例成員變量。
4.抽象類中的抽象方法的訪問類型能夠是public , protected和默認訪問權限。但接口中的抽象方法只能是public類型的。
5.抽象類中能夠包含static靜態方法,接口中不能包含static靜態方法。
6.抽象類和接口均可以包含靜態成員變量,但抽象類的靜態成員變量的訪問類型能夠是任意,而接口的靜態成員變量的訪問類型只能是public static final
二者在應用上的區別:
接口體現的是一種規範,而抽象類在代碼實現方面發揮做用,能夠實現代碼的重用。
例如,模板設計模式是抽象類的一個典型應用。假設項目中須要大量的DAO組件,這些組件一般都有增,刪,改,查等基本方法。所以咱們就能夠定義一個抽象的DAO基類,而後讓其它DAO組件來繼承這個抽象的DAO基類,把這個DAO基類當成模板使用。
44.abstract抽象的method方法是否可同時是static,是否可同時是native(原生態方法,方法對應的實現不在當前文件,而是在其餘語言(c,c++)實現的文件中),是否可同時是synchronized同步的?
答:抽象的方法不能夠是static的,由於抽象方法要被子類實現。
native方法表示該方法要用另外一種依賴平臺的編程語言實現,不存在着被子類實現的問題,因此,它也不能是抽象的。
Synchronized同步鎖與abstract不能同時使用,它修飾一個方法時,表示將會使用該方法的調用者做爲同步監視器。但abstract方法所在的類是抽象類,不能建立實例,所以沒法肯定synchronized修飾方法時的同步監視器。
45.什麼是內部類?Static Nested Class(靜態嵌入類型)和 Inner Class(插入類型)的不一樣。
答:內部類就是一個在類的內部定義的類,內部類中不能定義靜態成員。
靜態成員不能訪問非靜態成員, 所以靜態內部類不能訪問外部類的非靜態成員。
若是內部類使用了static修飾,該內部類就是靜態內部類,也就是所謂的static nested class。
若是內部類沒有使用inner修飾,它就是Inner class。
除此以外,還有一種局部內部類,在方法中定義的內部類就是局部內部類,局部內部類只在方法中有效。
對於Inner class而言,它屬於實例成員,所以Inner class的實例必須寄生在外部類的實例中,所以程序在建立Inner Class實例以前,必須先得到它所寄生的外部類的實例。不然程序沒法建立Inner Class的實例。
46.內部類能夠引用它的外部類的成員嗎?有沒有什麼限制?
答:內部類能夠訪問所在外部類的成員。
可是因爲Java中,靜態成員不能訪問非靜態成員,所以靜態內部類(屬於靜態成員)就不能訪問外部類的非靜態成員。
47.Anonymous Inner Class(匿名內部類)是否能夠extends(繼承)其它類,是否能夠implements(實現)interface(接口)?
答:匿名內部類能夠繼承其餘類或實現其它接口。
鑑於匿名內部類的特殊語法
new 父類、接口(){
類體實現部分
}
因此匿名內部類因爲語法緣由必需要實現父類或接口。
48.super.getClass()方法調用
下面程序的輸出結果是多少?
import java.util.Date;
public class Test extends Date{
public static void main(String[] args) {
new Test().test();
}
public void test(){
System.out.println(super.getClass().getName());
}
}
輸出結果:Test。
Super是一個限定詞,當用super引用時,它也是引用當前對象自己,只是super限定了訪問當前對象從父類那裏獲得成員變量和方法。
若是要訪問父類的類名,應該使用以下語法:
Super.getClass().getSupserClass().getName();
49.JDK中哪些類是不可繼承的?
答:不能繼承的類是用final關鍵字修飾的類。
使用final關鍵字修飾的類,能夠阻止被繼承,不會有子類來重寫該類的方法,徹底封閉起來,所以更安全。
50.String s = 「Hello」;
s = s + 「world!」;這兩行代碼執行後,原始String對象中的內容到底變了沒有?
答:沒有。String被設計成是一個不可變類。當第2行代碼執行之後,s引用變量指向了一個新的對象,原來的內容爲」Hello」直接量對象被存放在內存中。
建議使用StringBuffer或StringBuilder類。
51.是否能夠繼承String類?
答:String類是final類,被final關鍵字修飾,因此不能被繼承。
52.如何把一段逗號分割的字符串轉換成一個數組?
答:可使用String.split(「,」)方法使用String[]數組接收。
如:String [] result = "this,is,a,test".split(",");
其中result數組中存放了this、is、a、test等字符串元素。
53.下面這條語句一共建立了多少個對象:String s=」a」+」b」+」c」+」d」;
答:一個String對象。Java會在編譯時對字符串相加進行優化處理,在編譯時發現全部參與運算的都是字符串直接量,Java會把這個表達式的值計算出來。直接將該表達式的結果賦值給字符串引用變量。
對於以下代碼:
String s1=」a」;
String s2=s1 + 「b」;//對象+字符串=新的對象,和字符串常量池中的直接量沒有關係
String s3=」a」 + 「b」;
System.out.println(s2 == 「ab」);//false
System.out.println(s3 == 「ab」);//true
字符串直接量會被放入字符串緩衝池中。
以下兩行代碼:
String s = 「a」 + 「b」 + 「c」 + 「d」;
System.out.println(s == 「abcd」);//true
因爲s引用了字符串緩衝池中的」abcd」字符串,所以上面的輸出結果爲true。
54.Collection集合框架中實現比較要實現什麼接口。
答:Java集合框架中須要比較大小的集合包括TreeMap、TreeSet,其中TreeMap會根據key-value對中key的大小進行排序,而TreeSet則會對集合元素進行排序。
集合框架中比較大小有2種方式:
A. 天然排序
要求TreeMap中的全部key都實現Comparable接口。JDK不少類都已經實現了Comparable接口,如String,Date,BigDecimal等。
B. 定製排序
須要在建立TreeMap或TreeSet時傳入一個Comparator對象,Comparator只是一個接口,所以建立Comparator對象只能是建立它的實現類的對象,因此須要實現Comparator接口。
55.ArrayList和Vector的區別?
答:
Collection是接口,Collections是工具類。
相同點:這兩個類都實現了List接口,List接口繼承了Collection接口,它們都是有序集合。
(咱們能夠按位置索引號取出某個元素,而且其中的數據是容許重複的,這是List集合規範制定的)
並且ArrayList與Vector底層都是基於數組的,所以它們的實現代碼也大體類似。
區別:在於Vector是一個古老的集合,從JDK1.0開始就有了,所以它包含了大量方法名很長的方法。JDK1.2開始引入集合框架,引入List接口,才讓Vector實現了List接口,所以又增長了一些List接口中定義的方法。
整體來講,ArrayList能夠徹底替代Vector,除了在一些很古老的API中強制要求使用Vector以外。
Vector還有一個特徵,它是線程安全的,所以性能較差,而ArrayList並非線程安全的,所以性能較好。
實際上即便咱們要在多線程環境下使用List集合,也應該選擇ArrayList而不是Vector,由於Java還提供了一個Collections工具類,它能夠把ArrayList包裝成線程安全的集合類,例如以下代碼:
List list = Collections.synchronizedList(new ArrayList());
56.HashMap和HashTable的區別
答:HashMap和HashTable的區別相似於ArrayList與Vector的區別。
HashTable與Vector都是JDK1.0就有一個古老的集合,HashTable是一個繼承自Dictionary(字典)類的古老集合。
從JDK1.2引入集合框架的Map接口以後,Java讓HashTable也實現了Map接口,所以HashTable也新增實現了一些Map接口中定義的方法。
實際上HashMap與HashTable底層的實現很類似,它們都是基於Hash表的實現。
HashMap與HashTable的區別主要有2點:
A. HashMap容許null做爲key或value,而HashTable不容許。
B. HashMap是線程不安全的,所以性能較好。HashTable是線程安全的,所以性能較差。
實際上在多線程環境下,Java提供了Collection工具類把HashMap包裝成線程安全的類,所以依然應該使用HashMap,以下代碼所示:
Map map = Collections. synchronizedMap(new HashMap());
簡單的說,編程時應該儘可能避免使用HashTable,它與HashMap的底層實現很類似,但除非在一個古老的API中強制要求HashTable。
57.List和Map的區別?
答:List集合的特色:可重複,有序,有索引,程序能夠經過元素的索引來讀取元素,所以List至關於一個動態數組。
Map集合的特色:有Key-Value對,不容許重複,無序,無索引,程序能夠根據key來取出對應的Value。
深刻闡述:若是換個角度來看,咱們能夠把List當成Map來看,List至關於key都是數值的Map,程序經過元素的索引來讀取List集合時,徹底能夠當成Map根據key來讀取value。從另外一個角度看,Map也能夠當成元素索引能夠是任意類型的List集合。
58.List,Set,Map是否繼承自Collection接口?
答:List,Set集合繼承自Collection接口,Map集合很多繼承自Collection接口。
59.List,Map,Set三個接口,存取元素時,各有什麼特色?
答:List集合:可重複,有序,有索引,實現類,ArrayList
Set集合:不容許重複,無序,無索引
對於Map集合而言,其底層存,取性能與Set集合徹底同樣。其實Set集合自己就是基於Map實現的,除了有鍵值對之外。
60.說出ArrayList,Vector,LinkedList的存儲性能和特性。
答:ArrayList和Vector都是使用數組方式存儲數據,Vector因爲使用了synchrnized(線程安全)的方法,所以性能較ArrayList差,而LinkedList使用了雙向鏈表實現存儲,因此插入速度較快,並且線程也是不安全的。LinkedList提供了一些方法,使得LinkedList能夠被看成堆棧和隊列來使用。
實際上Java提供了Collection集合的工具類,它能夠把ArrayList,vector包裝成線程安全的集合,所以在實際編程中應該避免使用Vector集合,它是一個古老的,在JDK1.0時代就出現的集合。
61.去掉一個Vector集合中重複的元素。
最簡單的方式:HashSet set = new HashSet(vector);
基於HashSet不容許重複的特性。
62.Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢?是用==仍是equals()?它們有何區別?
答:Set只是一個接口,它的不一樣實現類判斷元素是否相等的標準是不一樣的。籠統地說,Set裏的元素是不能重複的,判斷元素重複應該使用equals方法而不是==。
對於HashSet而言,判斷兩個對象是否相等是經過equals()方法和hashCode()方法,只要兩個對象經過equals()比較返回false,或兩個對象的hashCode值不同,那麼HashSet就會把它們當成不相同的元素。
對於TreeSet而言,判斷兩個對象是否相等的惟一標準是:兩個對象經過compareTo(Object obj)比較是否返回0,與equals()方法無關。
63.你所知道的集合類都有哪些?主要方法?
答:最經常使用的集合接口是Set,List,Queue,它們都是Collection的子接口,除此以外還有Map接口。
對於Set集合而言,它的經常使用實現類包括HashSet與TreeSet,HashSet還有一個子類,LinkedHashSet。
對於List集合而言,它的經常使用實現類包括ArrayList,Vector與LinkedList。
對於Queue集合而言,它有一個子接口,表明雙端隊列,Deque,它的經常使用實現類包括ArrayDeque,LinkedList。
對於Map集合而言,它的經常使用實現類是HashMap,TreeMap,HashMap還有一個子類,LinkedHashMap。
至於這些集合的方法,因爲集合類也就是「容器類」,所以它的方法無非就是向容器中添加,刪除,取出,遍歷元素的方法。
List集合的元素都是有序,有索引的,所以它包括了大量根據索引來添加,刪除,取出集合元素的方法。
對於Deque集合而言,因爲它是雙端隊列,既能夠當成隊列使用,也能夠當成棧使用,所以它增長棧,隊列的方法,壓棧和彈棧,如push,pop,offer,peek等。
對於Map集合而言,它的方法無非就是根據key來添加,刪除,取出value的方法。
64.兩個對象值相同(x.equals(y)==true),但卻能夠有不一樣的hash code,這句話對不對?
答:對。
由於equals方法和hashcode方法均可以由開發者來重寫,所以它們是否相等並無必然的關係。
若是對象要保存在HashSet或者HashMap中,它們的equals相等,那麼hashcode返回值也應該相等。
65.TreeSet裏面放對象,若是同時放入了父類和子類的實例對象,那比較時使用的是父類的compareTo方法,仍是使用子類的compareTo方法,仍是拋異常?
答:當前正在添加父類對象就屢次調用父類對象的CompareTo方法,當前正在添加子類對象就屢次調用子類對象的CompareTo方法。
至於程序是否拋出異常,則取決於CompareTo方法的實現,若是子類在實現CompareTo方法時,試圖把被比較對象轉換爲子類對象以後再比較,若是TreeSet集合中已經包括了父類對象,這就會引發ClassCastException類型轉換異常。
66.說出一些經常使用的類,包,接口,請各舉5個。
答:經常使用的包有:
java.lang包下包括Math,System,StringBuilder,StringBuffer,Runtime,Thread,Runnable等
(Math數學,System系統,StringBuilder/StringBuffer,運行時類,線程類)
java.util包下包括List,Set,Map,以及這些接口的經常使用實現類,ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap等
java.io包下包括
(字節流,字符流,緩衝流)
InputStream,OutputStream,Reader,Writer,FileInputStream,FileOutputStream,FileReader,FileWriter,BufferInputStream,BufferOutputStream,BufferReader,BuffWriter等
Java.sql包下包括Connection,Statement,PrepareStatement,ResultSet等(建立鏈接對象,編譯,預編譯語句,結果集)
Java.net包下包括
Socket,ServerSocket,URL,URLConnection,DatagramPacker,DatagramSocket等
(Socket套接字)
67.java中有幾種類型的流?JDK爲每種類型的流提供了一些抽象類以繼承,請說出它們分別是那些類?
答:字節流和字符流,字節流由InputStream,OutputStream派生出來,字符流由Reader,Writer派生出來。在java.io包中還有許多其它的流,主要是爲了提升性能和使用方便。
68.字符流和字節流的區別。
答:字節流和字符流的區別是,它們的用法幾乎徹底同樣,區別在於字節流和字符流所操做的數據單元不一樣,字節流操做的數據單元是8位的字節,而字符流操做的數據單元是16位的字符。
節流主要由InputStream,OutputStream做爲基類,字符流主要由Reader,Writer做爲基類。
字節流是基於字節輸入,輸出的,所以它的適用性更廣。字符流則在處理文本內容時的輸入,輸出更加方便——不會出現只讀取半個字符的狀況。
Java提供了將字節流轉換爲字符串的InputStreamReader , OutputStreamWriter,但沒有提供將字符流轉化爲字節流的方法。由於,字節流比字符流的使用範圍更廣,但字符流在處理字符的時候比字節流操做方便。若是有一個字節流,咱們知道它的內容是文本內容,所以把它轉換成字符流來處理就會更方便一些。各有所需。
69.什麼是Java序列化,如何實現Java序列化?或者請解釋Serializable接口的做用。
答:序列化的目標是將對象保存到磁盤中,或容許在網絡中直接傳輸對象,對象序列化機制容許把內存中的Java對象轉換成平臺無關的二進制流,持久保存到磁盤上,經過網絡將這種二進制流傳輸到另外一個網絡節點。其它程序一旦得到了這種二進制流,不管是從磁盤中獲取仍是經過網絡獲取,均可以將這種二進制流恢復成原來的Java對象。
Serializable接口只是一個標記接口,實現該接口無需實現任何方法,實現了該接口的類就是可序列化的類。
序列化在Web開發中十分重要,Tomcat在某些時候須要把保存在Session中的對象序列化到硬盤,所以放入Session中的對象必須是可序列化的,這就能夠經過Serializable接口來實現。還有,若是一個對象要通過網絡傳輸(好比RMI遠程方法調用的形參或返回值),這個對象也應該是可序列化的。
70.描述一下JVM加載class文件的原理機制?
答:
當程序主動使用某個類,若是該類還未必加載到內存中,系統會經過3個步驟來對該類進行初始化。加載,鏈接,初始化。
類加載指的當程序中使用任何類時,系統都會爲之創建一個java.lang.Class類對象。
類的加載由加載器完成,類加載器一般由JVM提供,除此以外,開發者能夠經過繼承ClassLoader基類來建立本身的類加載器。
71.heap和stack有什麼區別?
答:stack指的是棧區,當程序進入一個方法時,系統會專門爲這個方法分配一個內存空間,這塊內存空間也被稱爲該方法棧區,該方法的棧區專門用於存儲該方法中定義的局部變量,(括基本類型變量和引用變量)。當這個方法結束時,該方法棧區將會自動被銷燬,棧區中的全部局部變量也會被銷燬。
heap指的是堆,堆內存是Java虛擬機擁有的內存區。全部的Java對象都被放在堆內存中,位於堆內存中的Java對象由系統垃圾回收器負責跟蹤管理——垃圾回收(GC),當堆內存中的對象沒有引用變量引用它時,這個Java對象就變成了垃圾,垃圾回收器會在合適的時候回收它
72.try{}裏有一個return語句,那麼緊跟在這個try後的finally{}裏的code會不會被執行,何時被執行,在return前仍是return後?
答:確定會執行,在return後執行。
Finally{}塊的代碼只有在try{}塊中包含遇到System.exit(0;之類的致使Java虛擬機直接退出的語句纔會不執行。
當程序執行try{}遇到return時,程序會先執行return語句,但並不會當即返回,而是把執行流程轉到finally塊,完成finally塊的執行後就直接返回剛纔return語句已經準備好的結果。
73.下面程序代碼輸出的結果是多少?
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
Java會把return語句先執行完,把全部須要處理的東西都先處理完成,可是還未返回以前,程序流程會轉去finally塊。但若是在執行finally塊時遇到了return語句,那麼程序會直接使用finally塊中的return語句來返回,所以上面程序會輸出2。
74.final,finally,finalize的區別。
答:final最終的,finally最後,finalize完成。
Final是一個修飾符,它能夠修飾類,方法,變量。
(final修飾類代表這個類不能夠被繼承,final修飾方法時代表這個方法不能夠被其子類重寫(重寫就是覆蓋Override.final,final修飾變量可分爲局部變量,實例變量,靜態變量。)
當final修飾局部變量時,該局部變量能夠被賦值一次。當final修飾實例變量時,實例變量必須由程序在構造器,初始化塊,」定義時」 這3個位置的其中之一指定初始值。當final修飾靜態變量時,靜態變量必須由程序在靜態初始化塊,定義時這2個位置的其中之一指定初始值。
Finally是異常處理語句結構的一部分,表示總會執行的代碼塊。
Finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法。但實際上重寫此方法進行資源回收並不安全,由於JVM並不保證該方法總被調用。
75.運行時異常與通常異常有何異同?
答:Checked檢查異常就是通常異常,體現了Java的設計哲學,沒有完善錯誤處理的代碼根本不會被執行。
通常異常的處理方式有2種,
A. 當前方法知道如何處理異常,程序應使用try…catch塊來捕獲異常,而後在對應的catch塊中修補該異常。
B. 當前方法不知道如何處理異常,應該在定義方法時聲明拋出該異常。Throw Exception
Runtime異常對比處理更加靈活,Runtime異常無需顯式聲明拋出,若是程序須要捕捉Runtime異常,也可使用try…catch塊來捕捉runtime異常。
76.error和exception有什麼區別?
答:Error錯誤,通常是指虛擬機相關的問題,如系統崩潰,虛擬機出錯,動態鏈接失敗等。這種錯誤沒法恢復或不能被捕獲,將致使應用程序中斷。
Exception異常,表示一種設計或實現問題。也就是說,程序員應該對這些狀況進行考慮,並提供相應的處理。
77.Java中的異常處理機制的簡單原理和應用。
答:程序運行過程當中可能出現各類「非預期「狀況,這種非預期狀況可能致使程序非正常結束。爲了提升程序的健壯性,Java提供了異常處理機制。
Java對異常進行了分類,不一樣類型的異常分別用不一樣的Java類表示,全部異常的根類爲java.lang.Throwable,Throwable下面又派生了兩個子類:Error錯誤和Exception異常,Error錯誤通常是指虛擬機相關的問題,如系統崩潰,虛擬機出現錯誤,動態鏈接失敗等。這種錯誤沒法恢復或不能捕獲,將致使應用程序中斷。一般應用程序沒法處理這種錯誤,所以不能使用try…catch{}塊來捕獲Error對象。
Exception表示一種設計或實現問題,也就是說,程序員應該對這些狀況進行考慮,並提供相應的處理。
異常分爲運行時異常和通常檢查異常,通常檢查異常體現了Java的設計哲學,沒有完善錯誤的代碼根本就不會被執行。
對於通常檢查異常的處理方式有兩種:
A. 當前方法知道如何處理異常,程序應使用try…catch塊來捕獲異常,而後在對應的catch塊中修補該異常。
B. 當前方法不知道如何處理異常,應該在定義方法時聲明拋出該異常。
實際上Java的通常異常後來爭議不斷,由於通常異常要求程序員要麼顯式聲明拋出,要麼進行捕捉,不能對通常異常漠不關心,這就給編程帶來了必定的複雜度。
好比Spring,Hibernate框架的一大特色就是把通常異常包裝成了運行時異常。
運行時異常則比較靈活,開發者既能夠選擇捕獲運行時異常,也能夠不捕獲。
78.請寫出你最多見到的5個runtime exception.
答:對於一個有1—2年左右編程經驗的人來講,總會遇到一些常見的異常。
其中有些就是
Runtime Exception運行時異常。
NullPointerException空指針異常:當調用一個未初始化的引用變量的實例Field,實例方法時都會引起該異常。
ArithmeticException算術異常:好比5/0將引起異常。
ArrayIndexOutOfBoundsException數組索引越界異常。
ClassCastException類型轉換異常。
IllegalArgumentException參數非法的異常。
79.Java語言如何進行異常處理,關鍵字:throws ,throw ,try ,catch ,finally分別表明什麼意義?在try塊中能夠拋出異常嗎?
答:try塊表示程序正常的業務執行代碼。若是程序在執行try塊的代碼時出現了「非預期」狀況,JVM將會生成一個異常對象,這個異常對象將會被後面相應的catch塊捕獲。
Throw用於手動拋出異常對象。Throw後面須要一個異常對象。
Throws用於在方法簽名中聲明拋出一個或多個異常類,throws關鍵字後能夠緊跟一個或多個異常類。
Finally塊表明異常處理流程中總會執行的代碼塊。
對於一個完整的異常處理流程,try塊是必須的,try塊後能夠緊跟一個或多個catch塊,最後還能夠帶一個finally塊。
Try塊中能夠拋出異常。
80.Java中有幾種方法能夠實現一個線程?用什麼關鍵字修飾同步方法?stop()和suspend()方法爲什麼不推薦使用?
答:在java5之前,有以下兩種
A. 繼承Thread類,重寫它的run()方法。
代碼以下:
new Thread()
{
public void run()
{
//線程執行體
}
}.start();
C. 實現Runnable接口,並重寫它的run()方法。
new Thread(new Runnable()
{
public void run()
{
//線程執行體
}
}).start();
從上面代碼不難看出,線程的執行體是一個run()方法,而後程序經過start()方法啓動一條線程。
從Java5開始,Java提供了第三種方式來建立多線程:實現Callable接口,並實現Call()方法。Callable接口至關於Runnable接口的加強版,由於Callable接口中定義的call()方法既擁有返回值,也能夠聲明拋出異常。
代碼以下:
new Thread(new FutureTask<Object >(new Callable<Object>()
{
public Object call() throws Exception
{
//線程執行體
}
})).start();
不只如此,Java5還提供了線程支持,ExecutorService對象就表明了線程池,若是開發者利用ExecutorService來啓動線程,ExecutorService底層會負責管理線程池。此時,開發者只要把Runnable對象傳給ExecutorService便可。以下代碼:
ExecutorService pool = Executors.newFixedThreadPool(3)
pool.execute(new Runnable()
{
public void run()
{
//線程執行體
}
});
若是執行經過Callable方式實現的線程,則可按以下代碼:
ExecutorService pool = Executors.newFixedThreadPool(3)
pool.execute(new FutureTask<Object >(new Callable<Object>()
{
public Object call() throws Exception
{
//線程執行體
}
}));
用synchronized關鍵字修飾同步方法。須要指出的是,非靜態的同步方法的同步監視器是this,也就是調用該方法的對象,而靜態的同步方法的同步監視器是該類自己。所以使用synchronized修飾的靜態方法,非靜態方法的同步監視器並不相同,只有基於同一個同步監視器的同步方法,同步代碼塊才能實現同步。
使用stop()中止方法不安全。它會解除由線程獲取的全部鎖定,並且若是對象處於一種不連貫狀態,那麼其餘線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。
Suspend()延遲方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這以前得到的鎖定。此時,其餘任何線程都不能訪問鎖定的資源,除非被「掛起」的線程恢復運行。對任何線程來講,若是它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會形成死鎖。因此不該該使用suspend(),而應在本身的Thread類中置入一個標誌,指出線程應該活動仍是掛起。若標誌指出線程應該掛起,便用wait()命其進入等待狀態。若標誌指出線程應當恢復,則用一個notify()從新啓動線程。
82.sleep()和wait()又什麼區別?
答:sleep()是Thread類的靜態方法,它的做用是讓當前線程從運行狀態轉入,阻塞狀態,線程執行暫停下來,當一個線程經過sleep()方法暫停以後,該線程並不會釋放它對同步監視器的加鎖。
Wait()是Object對象的方法,但實際上只有同步監視器才能調用該方法。當程序在同步代碼塊,或同步方法內經過同步監視器調用該方法時,將會致使當前線程釋放對該同步監視器的加鎖,而該線程則會進入該同步監視器的等待池中,直到該同步監視器調用notify()(通知)或notifyAll()來通知該線程。
83.同步和異步有何異同,在什麼狀況下分別使用它們?舉例說明。
答:同步,對於一個銀行帳戶,若是有多個線程試圖去訪問這個帳戶時,若是不對多個線程進行同步控制,有可能帳戶餘額只有1000塊,但多個線程都試圖取款800塊時,這些線程同時判斷餘額以後,都會顯示餘額足夠,從而致使每一個線程都取款成功。這顯然不是咱們但願看到的結果。
當程序試圖執行一個耗時操做時,程序不但願阻塞當前執行流,所以程序也不該該試圖當即獲取該耗時操做返回的結果,此時就使用異步編程了,典型的應用場景就是Ajax。當瀏覽器經過JavaScript發出一個異步請求以後,JavaScript執行流並不會停下來,而是繼續向下執行,這就是異步。程序會經過監聽器來監聽遠程服務器響應的到來。
84.多線程有幾種實現方法?同步有幾種實現方法?
答:
多線程的實現方法:
在Java5之前,有以下兩種:
第一種,繼承Thread類,重寫它的run()方法。
第二種,實現Runnable接口,並重寫它的run()方法。
線程的執行體是一個run()方法,而後程序經過start()方法啓動一條線程。
從Java5開始,Java提供了實現Callable接口來建立多線程,並實現call()方法。Callable接口至關於Runnable接口的加強版,由於Callable接口中定義的call()方法既擁有返回值,也能夠聲明拋出異常。
不只如此,Java5還提供了線程支持,ExecutorService對象就表明了線程池。開發者只要把Runnable對象,傳給ExecutorService便可。
同步的實現方法:
同步方法:使用synchronized關鍵字修飾方法,因爲java的每個對象都有一個內置鎖,在調用該方法前須要得到內置鎖,不然就處於阻塞狀態。
同步代碼塊:有synchronized關鍵字修飾的語句塊。
使用特殊域變量volatile實現線程同步,須要同步的變量加上volatile
使用重入鎖實現線程同步,建立一個ReentrantLock的實例,得到鎖lock(),釋放鎖unlock()。
使用局部變量實現線程同步,若是使用ThreadLocal管理變量,則每個使用該變量的線程都得到該變量的副本,副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響。
注:ThreadLocal與同步機制
A. ThreadLocal與同步機制都是爲了解決多線程中相同變量的訪問衝突問題。
B. 前者採用以「空間換時間」的方法,後者採用以「時間換空間」的方式。
85.啓動一個線程是用run()仍是start()?
答:啓動一個線程是調用start()方法,使線程就緒狀態,之後能夠被調度爲運行狀態。run()方法是線程的線程執行體——也就是線程將要完成的事情。
86.當線程進入一個對象的一個synchronized方法後,其餘線程是否能夠進入此對象的其餘方法?
答:當線程進入一個對象的synchronized方法以後,其餘線程徹底有可能再次進入該對象的其餘方法。
不過要分幾種狀況來看:
1. 若是其餘方法沒有使用synchronized關鍵字修飾,則能夠進入。
2. 若是當前線程進入的synchronized方法是static方法,其餘線程能夠進入其餘synchronized修飾的非靜態方法,若是當前線程進入的synchronized方法是非static方法,其餘線程能夠進入其餘synchronized方法。
3. 若是兩個方法都是靜態方法,或者都是非靜態方法,而且都使用了synchronized修飾,但只要在該方法內部調用了同步監視器的wait(),則其餘線程依然能夠進入其餘使用synchronized方法修飾的方法。
4. 若是沒有調用wait(),其餘線程不能進入其餘使用synchronized方法修飾的方法。
87.線程的基本概念,線程的基本狀態以及狀態之間的關係。
答:線程是進程的組成部分,一個進程能夠擁有多個線程,一個線程必須有一個父進程。線程能夠擁有本身的堆棧,本身的程序計數器和本身的局部變量,但再也不擁有系統資源,它與父進程的其餘線程共享該進程所擁有的所有資源。由於多個線程共享父進程裏的所有資源,所以編程更加方便;但必須更加當心,咱們必須確保線程不會妨礙同一進程裏的其餘線程。
線程的執行須要通過以下狀態:
新建線程new
就緒start()
運行
阻塞sleep()
死亡stop()
各狀態的轉換關係以下圖所示:
88.簡述synchronized和java . util .concurrent .locks .Lock的異同
答:主要相同點:Lock能完成synchronized所實現的全部功能。
主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能。Synchronized會自動釋放鎖,而Lock必定要求程序員手工釋放,而且必須在finally從句中釋放。Lock還有更強大的功能,它的tryLock方法能夠非阻塞方式去拿鎖。
Java代碼查錯部分
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
答:錯。abstract方法必須以分號;結尾,並且不帶花括號{}
2.
public class Something {
void doSomething () {
privateString s = "";
int l = s.length();
}
}
有錯嗎?
答:錯。局部變量前不能放置任何修飾符(private,public,和protected),final能夠用來修飾局部變量。
1. 面向對象的特徵有哪些方面?
答:
1. 繼承
經過繼承容許複用已有的類。繼承關係是一種通常到特殊的關係,好比蘋果類繼承水果類,這個過程稱爲類繼承。
子類能夠從父類那裏繼承獲得方法和成員變量,並且子類能夠修改或增長新的方法使之適合子類的須要。
2. 封裝
封裝是把對象的狀態數據隱藏起來,再經過暴露合適的方法來容許外部程序修改對象的狀態數據。Java的封裝主要經過private,protected,public等訪問控制符來實現。
3. 多態
多態指的是同一個類型的引用類型的變量在執行相同的方法時,實際上會呈現出多種不一樣的行爲特徵。
多態增長了編程的靈活性,實際上大量設計模式都是基於多態類實現的。
4. 抽象
抽象就是忽略與當前目標無關的方面,以便更充分的突出與當前目標有關的方面。
抽象包括兩個方面,一是過程抽象,二是數據抽象。
2. Java中實現多態的機制是什麼?
答:Java容許父類或接口定義的引用變量指向子類或具體實現類的實例對象,
(致使編譯時引用變量指向的方法和程序在內存裏運行時實例對象調用的方法不一致。)
而程序調用的方法在運行時才動態綁定,就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
3. 一個.java源文件中是否能夠包括多個類(不是內部類)?有什麼限制?
答:能夠有多個類,可是隻能有一個有public修飾的類,而且public類的類名必須與文件名相同。包含多個類的.java源文件編譯以後會產生多個.class文件。
4. String是最基本的數據類型嗎?
答:不是。
最基本的數據類型有:byte,short,int,long,char,float,double,Boolean
String是java.lang.String 類,屬於引用類型。
(所謂的引用類型包括:類,接口,數組。
由於String是final修飾的類,是不可繼承的類。而且是一個不可變類。所以若是程序須要使用的字符串所包含的字符序列須要常常改變,建議使用StringBuffer(線程安全,性能略差)類或者StringBuilder(線程不安全,性能好)類。)
5. Java有沒有goto (轉到)?
答:沒有。由於goto是Java的保留字,暫時不是Java的關鍵字。
6. int和Integer有什麼區別?
答:int是Java的基本數據類型,Integer是Java爲int提供的包裝類(封裝類)。Integer包裝類具備面向對象的特徵。
從Java5開始,Java提供了自動裝箱,自動拆箱功能。所以包裝類也能夠直接參與表達式運算,所以使用起來十分方便。
(Java爲每一個原始類型提供了包裝類。
在JSP開發中,Integer的默認值爲null,因此用EL輸出null的Integer時,會顯示空白字符串,而int的默認值爲0,因此int不適合做爲Web層的表單數據的類型。
另外,Integer提供了多個與整數相關的操做方法,例如,將一個字符串轉換成整數,Integer中還定義了表示整數的最大值和最小值的常量。)
7.String和StringBuffer,StringBuilder的區別?
答:
StringBuffer是線程安全的,性能較差,而StringBuilder是線程不安全的,適合單線程環境使用,性能較好。
String表明了字符序列不可變的字符串,而StringBuffer,StringBuilder表明了字符序列可變的字符串。
(它們都是CharSequence(字符序列)的實現類,均可以做爲字符串使用。
)
8.Collection和Collections的區別?
答:Collection是集合類(List集合,Set集合,Queue隊列)的根接口。
Collections是針對集合類的一個工具類,它提供一系列靜態方法實現對各類集合的搜索,排序,線程安全化等操做。
9.說說&和&&的區別?
答:
&和&&均可以用做邏輯與的運算符,&當運算符兩邊的表達式的結果都爲true時,整個運算結果才爲true,不然,只要有一方爲false,則結果爲false。
雙與有短路的功能,也稱短路與。若是第一個表達式爲false,則再也不計算第二個表達式了。實際開發中能夠用來把要比較的表達式放後面,排除報空指針異常的狀況。
而單與在第一個表達式爲false時,還會計算第二個表達式,因此性能略慢。
除此以外,&還能夠用做位運算符,當&操做符兩邊不是boolean類型時,&表示按位與操做。
10.Overload和Override的區別。
Overloaded的方法是否能夠改變返回值的類型?
答:Overload是方法的重載。(load 加載)
Override是方法的重寫,也叫覆蓋。
Overload要求兩個方法具備方法名相同,形參列表不一樣的要求,返回值類型不能做爲重載的條件。
Override要求子類方法與父類方法具備「兩同兩小一大」的要求。
兩同:父類方法,子類方法的方法名,形參列表相同。
兩小:子類方法的返回值類型要麼是父類方法返回值類型的子類,要麼返回值類型相同。
子類方法的拋出異常類型要麼是父類方法拋出異常類型的之類,要麼異常類型相同。
一大:子類的訪問權限要麼比父類的大,要麼相同。
Overloaded方法能夠改變返回值的類型。
11.Java如何跳出當前的多重嵌套循環?
答:能夠在外面的循環語句前定義一個標號,而後在裏層循環體的代碼中使用帶有標號的break語句,便可跳出外層循環。
例如:
Outer:
for(int i=0;i<10;i++)
{
for(int j=0;j<10;j++)
{
System.out.println(「i=」 + i + 「,j=」 + j);
if(j == 5) break Outer;
}
}
12.switch語句(判斷選擇)可否做用在byte上,可否做用在long上,可否做用在String上?
答:在Java1.7之前,能夠做用在char,byte,short,int以及對應的包裝類上。
在Java1.7之後,switch中能夠是字符串類型,因此能夠做用在String上。
也能夠是枚舉類型,在Java1.7之前以及之後都不能做用在long,double,float,boolean以及對應的包裝類上。
(long,double,float,long比較特殊)
13.String s = new String(「xyz」);建立了幾個String Object?
答:兩個。一個是直接量的xyz對象,另外一個是經過new String()構造器建立出來的String對象。一般來講,應該儘可能使用直接量的String對象,這樣具備更好的性能。
直接量就是程序中直接使用的數據值。
14.數組有沒有length()這個方法?String有沒有length()這個方法?
答:數組沒有length()這個方法,只有length這個屬性。String有length()方法。
Length長度。
15.short s1 = 1;s1 = s1 + 1;有什麼錯?short s1 = 1;s1+=s1有什麼錯?
答:s1 + 1 在運算時會自動提高表達式的類型,s1 + 1結果是int型,但複製給short類型的s1時,編譯器將報告須要強制轉換類型的錯誤。
第二個,因爲+=運算符裏已經包括了一個隱式的強制類型轉換,所以它不會有任何錯誤。
16.char型變量中能不能存儲一箇中文字符?爲何?
答:char型變量是用來存儲Unicode編碼的字符的,Unicode編碼字符集中包含了漢字,所以char型變量中能夠存儲漢字。
不過,若是某個特殊漢字沒有被包含在Unicode編碼字符集中,那麼,char型變量中不能存儲這個特殊漢字。
此外,char類型的變量佔兩個字節,而Unicode編碼中每一個字符也佔兩個字節。所以char型變量能夠存儲任何一個Unicode字符。
Unicode又稱統一碼。
17.用最有效率的方法算出2乘以8等於幾?
答:2<<3 ,<<,箭頭向左,是左移運算符,>>,箭頭向右,是右移運算符
由於將一個數左移n位,就至關於乘以了2的n次方;那麼,一個數乘以8只要將其左移3位便可,2的3次方,而CPU直接支持位運算,效率最高。
可是須要注意的是,若是這個數字自己已經很大,好比自己已是2的30次方了,此時再使用這種位移運算就可能致使「溢出」,這樣就得不到正確的結果了。
18.使用final關鍵字修飾一個變量時,是引用不能變,仍是引用的對象不能變?
答:使用final關鍵字修飾一個變量時,是指被修飾的引用變量不能變,引用變量所指向的對象的內容是能夠改變的。
例如,對於以下語句:
final StringBuilder a=new StringBuilder ("immutable");
執行以下語句將報告編譯錯誤:
a = new StringBuilder ("");
但以下語句則是徹底正確的
a.append("fkjava.org");
有人但願在定義方法的形參時,經過final修飾符來阻止方法內部修改傳進來的實參:
public void method(final StringBuilder param)
{
}
實際上這沒有用,在該方法內部仍然能夠增長以下代碼來修改實參對象:
param.append("fkjava.org");
19.」==」和equals方法究竟有什麼區別?
答:通俗地講,」==」比較左右是否是一個東西,equals是比較左右是否是長得同樣。
==操做符的功能有兩個:
A. 若是==的兩邊是基本類型的變量,包裝類對象所組成的表達式,==用於比較兩邊的表達式的值是否相等,若是值相等,即便數據類不一樣,也會返回true。
B. 若是==的兩邊是引用類型的變量,==用於判斷這兩個引用類型的變量是否引用同一塊內存,只有它們引用同一塊內存時,==纔會返回true。
C. 而equals()則是java.lang.Object類的一個方法,所以任何Java對象均可以調用此方法與其它對象進行比較。
D. 開發者重寫equals()方法就能夠根據業務要求來決定這兩個對象是否「相等」。
20.靜態變量和實例變量的區別?
答:A.在語法定義上的區別,靜態變量前要加static關鍵字,而實例變量前則不加。
B.在程序運行時的區別,實例變量屬於一個對象,必須先建立實例對象,它的實例變量纔會被分配空間,才能使用這個實例變量。靜態變量則屬於類,只要程序加載了類的字節碼,不用建立任何實例對象,靜態變量就會被分配空間,靜態變量就能夠被使用了。
總之,實例變量必須建立對象後才能夠經過這個對象來使用,靜態變量則能夠直接使用類名來引用。
C.在內存中,static修飾的類變量只能有一個,而實例變量每建立一個實例對象就能夠分配一個。
21.是否能夠從一個static方法內部調用非static方法?
答:不能夠,靜態成員不能夠調用非靜態成員。
非static方法屬於對象,必須建立一個對象後,才能夠經過該對象來調用實例方法。
而static方法調用時不須要建立對象,經過類就能夠調用該方法。
也就是說,當一個static方法被調用時,可能尚未建立任何實例對象。
所以Java不容許static方法內部調用非static方法。
22.Math.round(11.5)等於多少?Math.round(-11.5)等於多少?
答:Math類中提供了三個與取整有關的方法:ceil,floor,round,這些方法的做用與它們的英文名稱的含義相對應。Ceil:天花板,向上取整Math.ceil(11.3)=12,Math.ceil(-11.3)=-11
Floor:地板,向下取整Math.floor(11.6)的結果爲11,Math.floor(-11.6)=-12
Round:表示「四捨五入」,Math.round(11.5)=12,Math.round(-11.5)=-11。
23.請說出做用域public,private,protected,以及不寫時的區別。
答:這四個做用域的可見範圍以下表所示。
做用域 當前類 同一package 子類 全局
public √ √ √ √
protected √ √ √ ×
default √ √ × ×
private √ √ √ √
若是在修飾的元素上面沒有寫任何訪問修飾符,則表示default。
訪問權限由大到小是:public,protected,default,private
Java存在的4個訪問範圍:全局,子類,同一個package,當前類
24.外部類能用private,protected修飾嗎?內部類能夠用private,protected修飾嗎?
答:外部類不能用private,protected修飾。內部類能用private,protected修飾。
外部類的上一級程序單位是包package,所以它只能有兩個使用範圍:包內和包外,所以它只能使用public(表示能夠在全局位置訪問),和默認修飾符default(表示只能被同一個包內的其它類使用)修飾。
25.一個類定義多個重載方法,參數分別是int,char,和double,而後將double x=2傳遞進去,會選擇哪一個方法?
答:選擇參數類型爲double的方法。
26.說說has a(有)與is a(是)的區別。
答:is a是典型的「通常到特殊「的關係,也就是典型的繼承關係。例如Apple is a Fruit.。蘋果是水果。Apple是一種特殊的Fruit,也就是說Apple繼承了Fruit。
has a是典型的「組合「關係。好比Wolf has a Leg.狼有腿。也就是Leg組合成了Wolf。
須要指出的是:因爲繼承會形成對父類的破壞,所以有時候能夠經過組合來代替繼承。
使用繼承的好處:程序語義更好理解。壞處是:子類可能重寫父類方法,不利於父類封裝。
使用組合則形成語義的混淆,但組合類不會重寫被組合類的方法,所以更利於被複合類封裝。
27.ClassLoader如何加載Class?
答:JVM(Java虛擬機)裏有多個類加載,每一個類加載能夠負責加載特定位置的類。
除了bootstrap以外,其它的類加載器自己也是java類,它們的父類是ClassLoader。
28.Java抽象類的做用。
答:抽象類更利於代碼的維護和重用。
抽象類的特色:1.擁有抽象方法。
2.抽象方法和抽象類都必須被abstract關鍵字修飾。
3.抽象類不能夠建立實例和實例化對象,由於抽象類自己是不完整的。
4.抽象類的抽象方法要被使用,必須由子類重寫全部父類抽象類的抽象方法,創建子類對象調用。(若是子類只重寫(覆蓋)了部分抽象方法,那麼該子類仍是一個抽象類)
抽象類比通常類多了抽象方法。
28.GC是什麼?爲何要有GC?
答:GC是垃圾收集的意思,是Java的垃圾回收機制。
內存處理是編程人員容易出現問題的地方,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的。
Java的System和Runtime類都提供了「通知「程序進行垃圾回收的方法。
JVM什麼時候來進行垃圾回收,仍是由JVM本身來決定。
29垃圾回收的優勢和原理。並考慮2種回收機制。
答:
1.Java語言最顯著的特色就是引入了垃圾回收機制,它使java程序員在編寫程序時再也不考慮內存管理的問題。
2.因爲有垃圾回收機制,Java中的對象再也不有「做用域「的概念,只有引用的對象纔有做用域。
3.垃圾回收機制有效的防止了內存泄漏,能夠有效的使用可以使用的內存。
4.垃圾回收器一般做爲一個單獨的低級別的線程運行,在不可預知的狀況下對內存堆中已經死亡的或很長的時間沒有用過的對象進行清除和回收。
5.程序員不能實時的對某個對象或全部對象調用垃圾回收器進行垃圾回收。
垃圾回收機制有分代複製垃圾回收,標記垃圾回收,增量垃圾回收。
30.垃圾回收器的基本原理是什麼?垃圾回收器能夠立刻回收內存嗎?有什麼辦法主動通知虛擬機進行垃圾回收?
答:對於Java程序中對象而言,若是這個對象沒有任何引用變量引用它,那麼這個對象不能被程序訪問,所以可認爲它是垃圾。
1. 只要有1個以上的引用變量引用該對象,該對象就不會被垃圾回收。
2. 對於Java的垃圾回收器來講,它使用「有向圖「來記錄和管理堆內存中的全部對象,經過這個有向圖就能夠識別哪些對象是」可達的「(有1個引用變量引用該對象),哪些對象是」不可達的「,全部不可達的對象就會被垃圾回收。
3. 程序員能夠手動執行System.gc(),通知GC運行,但這只是一個通知,而JVM依然有權決定什麼時候進行垃圾回收。
31.何時用assert
答:assert是JDK1.4新增的關鍵字。
assertion斷言在軟件開發中是一種常見的調試方式,不少開發語言中都支持這種機制。在實現中,assert就是在程序中的一條語句,它對一個boolean表達式進行檢查,一個正確程序必須保證這個boolean表達式的值爲true,若是該值爲false,說明程序已經處於不正確的狀態下,assert將給出警告或退出。
Java的assert是關鍵字。
Java命令默認不啓動斷言,
爲了啓動用戶斷言,應該在運行java命令時增長-ea(Enable Assert)選項。
爲了啓動系統斷言,應該在運行java命令時增長-esa(Enable System Assert)選項。
32.Java中會存在內存泄漏嗎?請簡單描述。
答:什麼是內存泄漏:程序運行過程當中會不斷地分配空間;那些再也不使用的內存空間應該即時回收它們,從而保證系統能夠再次使用這些內存。若是存在無用的內存沒有被回收回來,那就是內存泄漏。
33.能不能本身寫個類,也叫java.lang.String?
答:能夠,但在應用的時候,須要用本身的類加載器去加載,不然,系統的類加載器永遠只是去加載jre.jar包中的那個java.lang.String。
但在Tomcat的web應用程序中,都是由webapp本身的類加載器先本身加載WEB-INF/classes目錄中的類,而後才委託上級的類加載器加載,若是咱們在Tomcat的web應用程序中寫一個java.lang.String,這時候Servlet程序加載的就是咱們本身寫的java.lang.String。但這樣作就會出不少潛在的問題,原來全部用了java.lang.String類都將出現問題。
34.ArrayList如何實現插入的數據按自定義的方式有序存放?
答:編程思路:實現一個類對ArrayList進行包裝,當程序試圖向ArrayList中放入數據時,程序將先檢查該元素與ArrayList集合中其餘元素的大小,而後將該元素插入到指定位置。
35.序列化接口的id有什麼用?
答:(對象的序列化:把對象轉換爲字節序列的過程.
對象的反序列化:把字節序列恢復爲對象的過程。
對象的序列化主要有兩種用途:
1. 把對象的字節序列永久地保存到硬盤上,一般放在一個文件中。
2. 在網絡上傳送對象的字節序列。
在不少應用中,須要對某些對象進行序列化,讓它們離開內存空間,入住物理硬盤,以便長期保存。)
反序列化Java對象時必須提供該對象的class文件,如今的問題是隨着項目的升級,系統的class文件也會升級,Java如何保證兩個class文件的兼容性?
Java序列化機制容許爲序列化類提供一個UID,也就是說若是一個類升級後,只要它的id值保持不變,序列化機制也會把它們當成同一個序列化版本。
(序列化類的id是爲了在進行項目升級時,保證系統的兩個class文件的兼容性,不會致使重複和衝突。)
36.hashCode()方法的做用?
答:hashCode()方法與equals()方法相似。都容許用戶定義子類重寫這兩個方法。
equals()主要判斷兩個對象表面上或者內容上看是否相同。
而hashCode方法的判斷就要嚴格的多。
若是兩個對象的hashCode()相等,便可認爲這兩個對象是相等的。
所以當咱們重寫一個類的equals()方法時,也應該重寫它的hashCode()方法。並且這兩個方法判斷對象的標準也應該是同樣的。
37.編寫一個函數將十六進制的字符串參數轉換成整數返回。
String str = 「13abf」;
Int len = str.length;
Int sum = 0;
Integer.parseInt(str,16);
parseInt方法提供了把16進制字符串參數轉換成整數返回的方法。
38.銀行還款問題
銀行貸款的還款方式中最經常使用的是一種叫「等額本息」,還款法,即借款人在約定還款期限內的每一期(月)歸還的金額(產生的利息+部分本金)都是相等的,現有一筆總額爲T元的N年期住房貸款,年利率爲R,要求算出每一期的還款的本金和利息總額,請寫出解決思路和任意一種編程語言實現的主要代碼。
思路:既然是按月還款,那我就要將N年按月來計算,即要還N*12個月,這樣就能夠求出每個月要還的本金。因爲每個月要還的那部分本金所欠的時間不一樣,因此,它們所產生的利息是不一樣的,該部分本金的利息爲:部分本金額*所欠月數*月利率。應該是這麼個算法,若是利息還計利息,若是月還款不按年利率來算,老百姓算不明白的。
39.*任意數字序列「123456」之類,輸出它們全部的排列組合
答:String str = "fkjav";
char[] arr1 = str.toCharArray();
char[] arr2 = java.util.Arrays.copyOf(arr1,arr1.length);
for(int i=0;i<arr1.length-1;i++)
{
for(int j = i+1;j<arr2.length;j++){
System.out.println(arr1[i] + "," + arr2[j]);
}
}
40.構造器Constructor是否可被override?
答:構造器Constructor不能被繼承,所以不能重寫Override,但能夠被重載Overrload(形參列表不一樣)。
41.接口是否能夠繼承接口?抽象類是否能夠實現(implements)接口?抽象類是否能夠繼承具體類(concrete class)?抽象類中是否能夠有靜態的main方法?
答:接口能夠繼承接口。
抽象類能夠實現接口。
抽象類能夠繼承具體類。
抽象類中能夠有靜態的main方法。
歸法:抽象類的特徵是有得有失,獲得的功能是抽象類能夠擁有抽象方法(固然也能夠沒有);失去的功能是抽象類不能建立實例了。至於其餘的,抽象類與普通類在語法上大體是同樣的。
(抽象類除了不能建立實例,只要普通類能夠的它均可以。)
42.寫clone()方法時,一般都有一行代碼,是什麼?
答:clone故名思意就是複製,當對象調用此方法,就會在內存中分配一個和源對象一樣大小的空間,在這個空間中建立一個新的複製對象。
clone有缺省(默認)行爲,super.clone();
由於首先要把父類中的成員複製到位,而後纔是複製本身的成員。
43.abstract class 和interface有什麼區別?
答:抽象類和接口的語法區別:
接口能夠說成是抽象類的一種特例,接口中全部方法都必須是抽象的。
1.一個類能夠實現多個接口,但只能繼承一個抽象類。
1.接口是完全的抽象類。抽象類能夠包含非抽象的普通方法,接口中的全部方法必須都是抽象的。
2.抽象類能夠有構造器,接口中不能有構造器。
3.抽象類中能夠有實例成員變量,接口中沒有實例成員變量。
4.抽象類中的抽象方法的訪問類型能夠是public , protected和默認訪問權限。但接口中的抽象方法只能是public類型的。
5.抽象類中能夠包含static靜態方法,接口中不能包含static靜態方法。
6.抽象類和接口均可以包含靜態成員變量,但抽象類的靜態成員變量的訪問類型能夠是任意,而接口的靜態成員變量的訪問類型只能是public static final
二者在應用上的區別:
接口體現的是一種規範,而抽象類在代碼實現方面發揮做用,能夠實現代碼的重用。
例如,模板設計模式是抽象類的一個典型應用。假設項目中須要大量的DAO組件,這些組件一般都有增,刪,改,查等基本方法。所以咱們就能夠定義一個抽象的DAO基類,而後讓其它DAO組件來繼承這個抽象的DAO基類,把這個DAO基類當成模板使用。
44.abstract抽象的method方法是否可同時是static,是否可同時是native(原生態方法,方法對應的實現不在當前文件,而是在其餘語言(c,c++)實現的文件中),是否可同時是synchronized同步的?
答:抽象的方法不能夠是static的,由於抽象方法要被子類實現。
native方法表示該方法要用另外一種依賴平臺的編程語言實現,不存在着被子類實現的問題,因此,它也不能是抽象的。
Synchronized同步鎖與abstract不能同時使用,它修飾一個方法時,表示將會使用該方法的調用者做爲同步監視器。但abstract方法所在的類是抽象類,不能建立實例,所以沒法肯定synchronized修飾方法時的同步監視器。
45.什麼是內部類?Static Nested Class(靜態嵌入類型)和 Inner Class(插入類型)的不一樣。
答:內部類就是一個在類的內部定義的類,內部類中不能定義靜態成員。
靜態成員不能訪問非靜態成員, 所以靜態內部類不能訪問外部類的非靜態成員。
若是內部類使用了static修飾,該內部類就是靜態內部類,也就是所謂的static nested class。
若是內部類沒有使用inner修飾,它就是Inner class。
除此以外,還有一種局部內部類,在方法中定義的內部類就是局部內部類,局部內部類只在方法中有效。
對於Inner class而言,它屬於實例成員,所以Inner class的實例必須寄生在外部類的實例中,所以程序在建立Inner Class實例以前,必須先得到它所寄生的外部類的實例。不然程序沒法建立Inner Class的實例。
46.內部類能夠引用它的外部類的成員嗎?有沒有什麼限制?
答:內部類能夠訪問所在外部類的成員。
可是因爲Java中,靜態成員不能訪問非靜態成員,所以靜態內部類(屬於靜態成員)就不能訪問外部類的非靜態成員。
47.Anonymous Inner Class(匿名內部類)是否能夠extends(繼承)其它類,是否能夠implements(實現)interface(接口)?
答:匿名內部類能夠繼承其餘類或實現其它接口。
鑑於匿名內部類的特殊語法
new 父類、接口(){
類體實現部分
}
因此匿名內部類因爲語法緣由必需要實現父類或接口。
48.super.getClass()方法調用
下面程序的輸出結果是多少?
import java.util.Date;
public class Test extends Date{
public static void main(String[] args) {
new Test().test();
}
public void test(){
System.out.println(super.getClass().getName());
}
}
輸出結果:Test。
Super是一個限定詞,當用super引用時,它也是引用當前對象自己,只是super限定了訪問當前對象從父類那裏獲得成員變量和方法。
若是要訪問父類的類名,應該使用以下語法:
Super.getClass().getSupserClass().getName();
49.JDK中哪些類是不可繼承的?
答:不能繼承的類是用final關鍵字修飾的類。
使用final關鍵字修飾的類,能夠阻止被繼承,不會有子類來重寫該類的方法,徹底封閉起來,所以更安全。
50.String s = 「Hello」;
s = s + 「world!」;這兩行代碼執行後,原始String對象中的內容到底變了沒有?
答:沒有。String被設計成是一個不可變類。當第2行代碼執行之後,s引用變量指向了一個新的對象,原來的內容爲」Hello」直接量對象被存放在內存中。
建議使用StringBuffer或StringBuilder類。
51.是否能夠繼承String類?
答:String類是final類,被final關鍵字修飾,因此不能被繼承。
52.如何把一段逗號分割的字符串轉換成一個數組?
答:可使用String.split(「,」)方法使用String[]數組接收。
如:String [] result = "this,is,a,test".split(",");
其中result數組中存放了this、is、a、test等字符串元素。
53.下面這條語句一共建立了多少個對象:String s=」a」+」b」+」c」+」d」;
答:一個String對象。Java會在編譯時對字符串相加進行優化處理,在編譯時發現全部參與運算的都是字符串直接量,Java會把這個表達式的值計算出來。直接將該表達式的結果賦值給字符串引用變量。
對於以下代碼:
String s1=」a」;
String s2=s1 + 「b」;//對象+字符串=新的對象,和字符串常量池中的直接量沒有關係
String s3=」a」 + 「b」;
System.out.println(s2 == 「ab」);//false
System.out.println(s3 == 「ab」);//true
字符串直接量會被放入字符串緩衝池中。
以下兩行代碼:
String s = 「a」 + 「b」 + 「c」 + 「d」;
System.out.println(s == 「abcd」);//true
因爲s引用了字符串緩衝池中的」abcd」字符串,所以上面的輸出結果爲true。
54.Collection集合框架中實現比較要實現什麼接口。
答:Java集合框架中須要比較大小的集合包括TreeMap、TreeSet,其中TreeMap會根據key-value對中key的大小進行排序,而TreeSet則會對集合元素進行排序。
集合框架中比較大小有2種方式:
A. 天然排序
要求TreeMap中的全部key都實現Comparable接口。JDK不少類都已經實現了Comparable接口,如String,Date,BigDecimal等。
B. 定製排序
須要在建立TreeMap或TreeSet時傳入一個Comparator對象,Comparator只是一個接口,所以建立Comparator對象只能是建立它的實現類的對象,因此須要實現Comparator接口。
55.ArrayList和Vector的區別?
答:
Collection是接口,Collections是工具類。
相同點:這兩個類都實現了List接口,List接口繼承了Collection接口,它們都是有序集合。
(咱們能夠按位置索引號取出某個元素,而且其中的數據是容許重複的,這是List集合規範制定的)
並且ArrayList與Vector底層都是基於數組的,所以它們的實現代碼也大體類似。
區別:在於Vector是一個古老的集合,從JDK1.0開始就有了,所以它包含了大量方法名很長的方法。JDK1.2開始引入集合框架,引入List接口,才讓Vector實現了List接口,所以又增長了一些List接口中定義的方法。
整體來講,ArrayList能夠徹底替代Vector,除了在一些很古老的API中強制要求使用Vector以外。
Vector還有一個特徵,它是線程安全的,所以性能較差,而ArrayList並非線程安全的,所以性能較好。
實際上即便咱們要在多線程環境下使用List集合,也應該選擇ArrayList而不是Vector,由於Java還提供了一個Collections工具類,它能夠把ArrayList包裝成線程安全的集合類,例如以下代碼:
List list = Collections.synchronizedList(new ArrayList());
56.HashMap和HashTable的區別
答:HashMap和HashTable的區別相似於ArrayList與Vector的區別。
HashTable與Vector都是JDK1.0就有一個古老的集合,HashTable是一個繼承自Dictionary(字典)類的古老集合。
從JDK1.2引入集合框架的Map接口以後,Java讓HashTable也實現了Map接口,所以HashTable也新增實現了一些Map接口中定義的方法。
實際上HashMap與HashTable底層的實現很類似,它們都是基於Hash表的實現。
HashMap與HashTable的區別主要有2點:
A. HashMap容許null做爲key或value,而HashTable不容許。
B. HashMap是線程不安全的,所以性能較好。HashTable是線程安全的,所以性能較差。
實際上在多線程環境下,Java提供了Collection工具類把HashMap包裝成線程安全的類,所以依然應該使用HashMap,以下代碼所示:
Map map = Collections. synchronizedMap(new HashMap());
簡單的說,編程時應該儘可能避免使用HashTable,它與HashMap的底層實現很類似,但除非在一個古老的API中強制要求HashTable。
57.List和Map的區別?
答:List集合的特色:可重複,有序,有索引,程序能夠經過元素的索引來讀取元素,所以List至關於一個動態數組。
Map集合的特色:有Key-Value對,不容許重複,無序,無索引,程序能夠根據key來取出對應的Value。
深刻闡述:若是換個角度來看,咱們能夠把List當成Map來看,List至關於key都是數值的Map,程序經過元素的索引來讀取List集合時,徹底能夠當成Map根據key來讀取value。從另外一個角度看,Map也能夠當成元素索引能夠是任意類型的List集合。
58.List,Set,Map是否繼承自Collection接口?
答:List,Set集合繼承自Collection接口,Map集合很多繼承自Collection接口。
59.List,Map,Set三個接口,存取元素時,各有什麼特色?
答:List集合:可重複,有序,有索引,實現類,ArrayList
Set集合:不容許重複,無序,無索引
對於Map集合而言,其底層存,取性能與Set集合徹底同樣。其實Set集合自己就是基於Map實現的,除了有鍵值對之外。
60.說出ArrayList,Vector,LinkedList的存儲性能和特性。
答:ArrayList和Vector都是使用數組方式存儲數據,Vector因爲使用了synchrnized(線程安全)的方法,所以性能較ArrayList差,而LinkedList使用了雙向鏈表實現存儲,因此插入速度較快,並且線程也是不安全的。LinkedList提供了一些方法,使得LinkedList能夠被看成堆棧和隊列來使用。
實際上Java提供了Collection集合的工具類,它能夠把ArrayList,vector包裝成線程安全的集合,所以在實際編程中應該避免使用Vector集合,它是一個古老的,在JDK1.0時代就出現的集合。
61.去掉一個Vector集合中重複的元素。
最簡單的方式:HashSet set = new HashSet(vector);
基於HashSet不容許重複的特性。
62.Set裏的元素是不能重複的,那麼用什麼方法來區分重複與否呢?是用==仍是equals()?它們有何區別?
答:Set只是一個接口,它的不一樣實現類判斷元素是否相等的標準是不一樣的。籠統地說,Set裏的元素是不能重複的,判斷元素重複應該使用equals方法而不是==。
對於HashSet而言,判斷兩個對象是否相等是經過equals()方法和hashCode()方法,只要兩個對象經過equals()比較返回false,或兩個對象的hashCode值不同,那麼HashSet就會把它們當成不相同的元素。
對於TreeSet而言,判斷兩個對象是否相等的惟一標準是:兩個對象經過compareTo(Object obj)比較是否返回0,與equals()方法無關。
63.你所知道的集合類都有哪些?主要方法?
答:最經常使用的集合接口是Set,List,Queue,它們都是Collection的子接口,除此以外還有Map接口。
對於Set集合而言,它的經常使用實現類包括HashSet與TreeSet,HashSet還有一個子類,LinkedHashSet。
對於List集合而言,它的經常使用實現類包括ArrayList,Vector與LinkedList。
對於Queue集合而言,它有一個子接口,表明雙端隊列,Deque,它的經常使用實現類包括ArrayDeque,LinkedList。
對於Map集合而言,它的經常使用實現類是HashMap,TreeMap,HashMap還有一個子類,LinkedHashMap。
至於這些集合的方法,因爲集合類也就是「容器類」,所以它的方法無非就是向容器中添加,刪除,取出,遍歷元素的方法。
List集合的元素都是有序,有索引的,所以它包括了大量根據索引來添加,刪除,取出集合元素的方法。
對於Deque集合而言,因爲它是雙端隊列,既能夠當成隊列使用,也能夠當成棧使用,所以它增長棧,隊列的方法,壓棧和彈棧,如push,pop,offer,peek等。
對於Map集合而言,它的方法無非就是根據key來添加,刪除,取出value的方法。
64.兩個對象值相同(x.equals(y)==true),但卻能夠有不一樣的hash code,這句話對不對?
答:對。
由於equals方法和hashcode方法均可以由開發者來重寫,所以它們是否相等並無必然的關係。
若是對象要保存在HashSet或者HashMap中,它們的equals相等,那麼hashcode返回值也應該相等。
65.TreeSet裏面放對象,若是同時放入了父類和子類的實例對象,那比較時使用的是父類的compareTo方法,仍是使用子類的compareTo方法,仍是拋異常?
答:當前正在添加父類對象就屢次調用父類對象的CompareTo方法,當前正在添加子類對象就屢次調用子類對象的CompareTo方法。
至於程序是否拋出異常,則取決於CompareTo方法的實現,若是子類在實現CompareTo方法時,試圖把被比較對象轉換爲子類對象以後再比較,若是TreeSet集合中已經包括了父類對象,這就會引發ClassCastException類型轉換異常。
66.說出一些經常使用的類,包,接口,請各舉5個。
答:經常使用的包有:
java.lang包下包括Math,System,StringBuilder,StringBuffer,Runtime,Thread,Runnable等
(Math數學,System系統,StringBuilder/StringBuffer,運行時類,線程類)
java.util包下包括List,Set,Map,以及這些接口的經常使用實現類,ArrayList,LinkedList,HashSet,TreeSet,HashMap,TreeMap等
java.io包下包括
(字節流,字符流,緩衝流)
InputStream,OutputStream,Reader,Writer,FileInputStream,FileOutputStream,FileReader,FileWriter,BufferInputStream,BufferOutputStream,BufferReader,BuffWriter等
Java.sql包下包括Connection,Statement,PrepareStatement,ResultSet等(建立鏈接對象,編譯,預編譯語句,結果集)
Java.net包下包括
Socket,ServerSocket,URL,URLConnection,DatagramPacker,DatagramSocket等
(Socket套接字)
67.java中有幾種類型的流?JDK爲每種類型的流提供了一些抽象類以繼承,請說出它們分別是那些類?
答:字節流和字符流,字節流由InputStream,OutputStream派生出來,字符流由Reader,Writer派生出來。在java.io包中還有許多其它的流,主要是爲了提升性能和使用方便。
68.字符流和字節流的區別。
答:字節流和字符流的區別是,它們的用法幾乎徹底同樣,區別在於字節流和字符流所操做的數據單元不一樣,字節流操做的數據單元是8位的字節,而字符流操做的數據單元是16位的字符。
節流主要由InputStream,OutputStream做爲基類,字符流主要由Reader,Writer做爲基類。
字節流是基於字節輸入,輸出的,所以它的適用性更廣。字符流則在處理文本內容時的輸入,輸出更加方便——不會出現只讀取半個字符的狀況。
Java提供了將字節流轉換爲字符串的InputStreamReader , OutputStreamWriter,但沒有提供將字符流轉化爲字節流的方法。由於,字節流比字符流的使用範圍更廣,但字符流在處理字符的時候比字節流操做方便。若是有一個字節流,咱們知道它的內容是文本內容,所以把它轉換成字符流來處理就會更方便一些。各有所需。
69.什麼是Java序列化,如何實現Java序列化?或者請解釋Serializable接口的做用。
答:序列化的目標是將對象保存到磁盤中,或容許在網絡中直接傳輸對象,對象序列化機制容許把內存中的Java對象轉換成平臺無關的二進制流,持久保存到磁盤上,經過網絡將這種二進制流傳輸到另外一個網絡節點。其它程序一旦得到了這種二進制流,不管是從磁盤中獲取仍是經過網絡獲取,均可以將這種二進制流恢復成原來的Java對象。
Serializable接口只是一個標記接口,實現該接口無需實現任何方法,實現了該接口的類就是可序列化的類。
序列化在Web開發中十分重要,Tomcat在某些時候須要把保存在Session中的對象序列化到硬盤,所以放入Session中的對象必須是可序列化的,這就能夠經過Serializable接口來實現。還有,若是一個對象要通過網絡傳輸(好比RMI遠程方法調用的形參或返回值),這個對象也應該是可序列化的。
70.描述一下JVM加載class文件的原理機制?
答:
當程序主動使用某個類,若是該類還未必加載到內存中,系統會經過3個步驟來對該類進行初始化。加載,鏈接,初始化。
類加載指的當程序中使用任何類時,系統都會爲之創建一個java.lang.Class類對象。
類的加載由加載器完成,類加載器一般由JVM提供,除此以外,開發者能夠經過繼承ClassLoader基類來建立本身的類加載器。
71.heap和stack有什麼區別?
答:stack指的是棧區,當程序進入一個方法時,系統會專門爲這個方法分配一個內存空間,這塊內存空間也被稱爲該方法棧區,該方法的棧區專門用於存儲該方法中定義的局部變量,(括基本類型變量和引用變量)。當這個方法結束時,該方法棧區將會自動被銷燬,棧區中的全部局部變量也會被銷燬。
heap指的是堆,堆內存是Java虛擬機擁有的內存區。全部的Java對象都被放在堆內存中,位於堆內存中的Java對象由系統垃圾回收器負責跟蹤管理——垃圾回收(GC),當堆內存中的對象沒有引用變量引用它時,這個Java對象就變成了垃圾,垃圾回收器會在合適的時候回收它
72.try{}裏有一個return語句,那麼緊跟在這個try後的finally{}裏的code會不會被執行,何時被執行,在return前仍是return後?
答:確定會執行,在return後執行。
Finally{}塊的代碼只有在try{}塊中包含遇到System.exit(0;之類的致使Java虛擬機直接退出的語句纔會不執行。
當程序執行try{}遇到return時,程序會先執行return語句,但並不會當即返回,而是把執行流程轉到finally塊,完成finally塊的執行後就直接返回剛纔return語句已經準備好的結果。
73.下面程序代碼輸出的結果是多少?
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
Java會把return語句先執行完,把全部須要處理的東西都先處理完成,可是還未返回以前,程序流程會轉去finally塊。但若是在執行finally塊時遇到了return語句,那麼程序會直接使用finally塊中的return語句來返回,所以上面程序會輸出2。
74.final,finally,finalize的區別。
答:final最終的,finally最後,finalize完成。
Final是一個修飾符,它能夠修飾類,方法,變量。
(final修飾類代表這個類不能夠被繼承,final修飾方法時代表這個方法不能夠被其子類重寫(重寫就是覆蓋Override.final,final修飾變量可分爲局部變量,實例變量,靜態變量。)
當final修飾局部變量時,該局部變量能夠被賦值一次。當final修飾實例變量時,實例變量必須由程序在構造器,初始化塊,」定義時」 這3個位置的其中之一指定初始值。當final修飾靜態變量時,靜態變量必須由程序在靜態初始化塊,定義時這2個位置的其中之一指定初始值。
Finally是異常處理語句結構的一部分,表示總會執行的代碼塊。
Finalize是Object類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法。但實際上重寫此方法進行資源回收並不安全,由於JVM並不保證該方法總被調用。
75.運行時異常與通常異常有何異同?
答:Checked檢查異常就是通常異常,體現了Java的設計哲學,沒有完善錯誤處理的代碼根本不會被執行。
通常異常的處理方式有2種,
A. 當前方法知道如何處理異常,程序應使用try…catch塊來捕獲異常,而後在對應的catch塊中修補該異常。
B. 當前方法不知道如何處理異常,應該在定義方法時聲明拋出該異常。Throw Exception
Runtime異常對比處理更加靈活,Runtime異常無需顯式聲明拋出,若是程序須要捕捉Runtime異常,也可使用try…catch塊來捕捉runtime異常。
76.error和exception有什麼區別?
答:Error錯誤,通常是指虛擬機相關的問題,如系統崩潰,虛擬機出錯,動態鏈接失敗等。這種錯誤沒法恢復或不能被捕獲,將致使應用程序中斷。
Exception異常,表示一種設計或實現問題。也就是說,程序員應該對這些狀況進行考慮,並提供相應的處理。
77.Java中的異常處理機制的簡單原理和應用。
答:程序運行過程當中可能出現各類「非預期「狀況,這種非預期狀況可能致使程序非正常結束。爲了提升程序的健壯性,Java提供了異常處理機制。
Java對異常進行了分類,不一樣類型的異常分別用不一樣的Java類表示,全部異常的根類爲java.lang.Throwable,Throwable下面又派生了兩個子類:Error錯誤和Exception異常,Error錯誤通常是指虛擬機相關的問題,如系統崩潰,虛擬機出現錯誤,動態鏈接失敗等。這種錯誤沒法恢復或不能捕獲,將致使應用程序中斷。一般應用程序沒法處理這種錯誤,所以不能使用try…catch{}塊來捕獲Error對象。
Exception表示一種設計或實現問題,也就是說,程序員應該對這些狀況進行考慮,並提供相應的處理。
異常分爲運行時異常和通常檢查異常,通常檢查異常體現了Java的設計哲學,沒有完善錯誤的代碼根本就不會被執行。
對於通常檢查異常的處理方式有兩種:
A. 當前方法知道如何處理異常,程序應使用try…catch塊來捕獲異常,而後在對應的catch塊中修補該異常。
B. 當前方法不知道如何處理異常,應該在定義方法時聲明拋出該異常。
實際上Java的通常異常後來爭議不斷,由於通常異常要求程序員要麼顯式聲明拋出,要麼進行捕捉,不能對通常異常漠不關心,這就給編程帶來了必定的複雜度。
好比Spring,Hibernate框架的一大特色就是把通常異常包裝成了運行時異常。
運行時異常則比較靈活,開發者既能夠選擇捕獲運行時異常,也能夠不捕獲。
78.請寫出你最多見到的5個runtime exception.
答:對於一個有1—2年左右編程經驗的人來講,總會遇到一些常見的異常。
其中有些就是
Runtime Exception運行時異常。
NullPointerException空指針異常:當調用一個未初始化的引用變量的實例Field,實例方法時都會引起該異常。
ArithmeticException算術異常:好比5/0將引起異常。
ArrayIndexOutOfBoundsException數組索引越界異常。
ClassCastException類型轉換異常。
IllegalArgumentException參數非法的異常。
79.Java語言如何進行異常處理,關鍵字:throws ,throw ,try ,catch ,finally分別表明什麼意義?在try塊中能夠拋出異常嗎?
答:try塊表示程序正常的業務執行代碼。若是程序在執行try塊的代碼時出現了「非預期」狀況,JVM將會生成一個異常對象,這個異常對象將會被後面相應的catch塊捕獲。
Throw用於手動拋出異常對象。Throw後面須要一個異常對象。
Throws用於在方法簽名中聲明拋出一個或多個異常類,throws關鍵字後能夠緊跟一個或多個異常類。
Finally塊表明異常處理流程中總會執行的代碼塊。
對於一個完整的異常處理流程,try塊是必須的,try塊後能夠緊跟一個或多個catch塊,最後還能夠帶一個finally塊。
Try塊中能夠拋出異常。
80.Java中有幾種方法能夠實現一個線程?用什麼關鍵字修飾同步方法?stop()和suspend()方法爲什麼不推薦使用?
答:在java5之前,有以下兩種
A. 繼承Thread類,重寫它的run()方法。
代碼以下:
new Thread()
{
public void run()
{
//線程執行體
}
}.start();
C. 實現Runnable接口,並重寫它的run()方法。
new Thread(new Runnable()
{
public void run()
{
//線程執行體
}
}).start();
從上面代碼不難看出,線程的執行體是一個run()方法,而後程序經過start()方法啓動一條線程。
從Java5開始,Java提供了第三種方式來建立多線程:實現Callable接口,並實現Call()方法。Callable接口至關於Runnable接口的加強版,由於Callable接口中定義的call()方法既擁有返回值,也能夠聲明拋出異常。
代碼以下:
new Thread(new FutureTask<Object >(new Callable<Object>()
{
public Object call() throws Exception
{
//線程執行體
}
})).start();
不只如此,Java5還提供了線程支持,ExecutorService對象就表明了線程池,若是開發者利用ExecutorService來啓動線程,ExecutorService底層會負責管理線程池。此時,開發者只要把Runnable對象傳給ExecutorService便可。以下代碼:
ExecutorService pool = Executors.newFixedThreadPool(3)
pool.execute(new Runnable()
{
public void run()
{
//線程執行體
}
});
若是執行經過Callable方式實現的線程,則可按以下代碼:
ExecutorService pool = Executors.newFixedThreadPool(3)
pool.execute(new FutureTask<Object >(new Callable<Object>()
{
public Object call() throws Exception
{
//線程執行體
}
}));
用synchronized關鍵字修飾同步方法。須要指出的是,非靜態的同步方法的同步監視器是this,也就是調用該方法的對象,而靜態的同步方法的同步監視器是該類自己。所以使用synchronized修飾的靜態方法,非靜態方法的同步監視器並不相同,只有基於同一個同步監視器的同步方法,同步代碼塊才能實現同步。
使用stop()中止方法不安全。它會解除由線程獲取的全部鎖定,並且若是對象處於一種不連貫狀態,那麼其餘線程能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。
Suspend()延遲方法容易發生死鎖。調用suspend()的時候,目標線程會停下來,但卻仍然持有在這以前得到的鎖定。此時,其餘任何線程都不能訪問鎖定的資源,除非被「掛起」的線程恢復運行。對任何線程來講,若是它們想恢復目標線程,同時又試圖使用任何一個鎖定的資源,就會形成死鎖。因此不該該使用suspend(),而應在本身的Thread類中置入一個標誌,指出線程應該活動仍是掛起。若標誌指出線程應該掛起,便用wait()命其進入等待狀態。若標誌指出線程應當恢復,則用一個notify()從新啓動線程。
82.sleep()和wait()又什麼區別?
答:sleep()是Thread類的靜態方法,它的做用是讓當前線程從運行狀態轉入,阻塞狀態,線程執行暫停下來,當一個線程經過sleep()方法暫停以後,該線程並不會釋放它對同步監視器的加鎖。
Wait()是Object對象的方法,但實際上只有同步監視器才能調用該方法。當程序在同步代碼塊,或同步方法內經過同步監視器調用該方法時,將會致使當前線程釋放對該同步監視器的加鎖,而該線程則會進入該同步監視器的等待池中,直到該同步監視器調用notify()(通知)或notifyAll()來通知該線程。
83.同步和異步有何異同,在什麼狀況下分別使用它們?舉例說明。
答:同步,對於一個銀行帳戶,若是有多個線程試圖去訪問這個帳戶時,若是不對多個線程進行同步控制,有可能帳戶餘額只有1000塊,但多個線程都試圖取款800塊時,這些線程同時判斷餘額以後,都會顯示餘額足夠,從而致使每一個線程都取款成功。這顯然不是咱們但願看到的結果。
當程序試圖執行一個耗時操做時,程序不但願阻塞當前執行流,所以程序也不該該試圖當即獲取該耗時操做返回的結果,此時就使用異步編程了,典型的應用場景就是Ajax。當瀏覽器經過JavaScript發出一個異步請求以後,JavaScript執行流並不會停下來,而是繼續向下執行,這就是異步。程序會經過監聽器來監聽遠程服務器響應的到來。
84.多線程有幾種實現方法?同步有幾種實現方法?
答:
多線程的實現方法:
在Java5之前,有以下兩種:
第一種,繼承Thread類,重寫它的run()方法。
第二種,實現Runnable接口,並重寫它的run()方法。
線程的執行體是一個run()方法,而後程序經過start()方法啓動一條線程。
從Java5開始,Java提供了實現Callable接口來建立多線程,並實現call()方法。Callable接口至關於Runnable接口的加強版,由於Callable接口中定義的call()方法既擁有返回值,也能夠聲明拋出異常。
不只如此,Java5還提供了線程支持,ExecutorService對象就表明了線程池。開發者只要把Runnable對象,傳給ExecutorService便可。
同步的實現方法:
同步方法:使用synchronized關鍵字修飾方法,因爲java的每個對象都有一個內置鎖,在調用該方法前須要得到內置鎖,不然就處於阻塞狀態。
同步代碼塊:有synchronized關鍵字修飾的語句塊。
使用特殊域變量volatile實現線程同步,須要同步的變量加上volatile
使用重入鎖實現線程同步,建立一個ReentrantLock的實例,得到鎖lock(),釋放鎖unlock()。
使用局部變量實現線程同步,若是使用ThreadLocal管理變量,則每個使用該變量的線程都得到該變量的副本,副本之間相互獨立,這樣每個線程均可以隨意修改本身的變量副本,而不會對其餘線程產生影響。
注:ThreadLocal與同步機制
A. ThreadLocal與同步機制都是爲了解決多線程中相同變量的訪問衝突問題。
B. 前者採用以「空間換時間」的方法,後者採用以「時間換空間」的方式。
85.啓動一個線程是用run()仍是start()?
答:啓動一個線程是調用start()方法,使線程就緒狀態,之後能夠被調度爲運行狀態。run()方法是線程的線程執行體——也就是線程將要完成的事情。
86.當線程進入一個對象的一個synchronized方法後,其餘線程是否能夠進入此對象的其餘方法?
答:當線程進入一個對象的synchronized方法以後,其餘線程徹底有可能再次進入該對象的其餘方法。
不過要分幾種狀況來看:
1. 若是其餘方法沒有使用synchronized關鍵字修飾,則能夠進入。
2. 若是當前線程進入的synchronized方法是static方法,其餘線程能夠進入其餘synchronized修飾的非靜態方法,若是當前線程進入的synchronized方法是非static方法,其餘線程能夠進入其餘synchronized方法。
3. 若是兩個方法都是靜態方法,或者都是非靜態方法,而且都使用了synchronized修飾,但只要在該方法內部調用了同步監視器的wait(),則其餘線程依然能夠進入其餘使用synchronized方法修飾的方法。
4. 若是沒有調用wait(),其餘線程不能進入其餘使用synchronized方法修飾的方法。
87.線程的基本概念,線程的基本狀態以及狀態之間的關係。
答:線程是進程的組成部分,一個進程能夠擁有多個線程,一個線程必須有一個父進程。線程能夠擁有本身的堆棧,本身的程序計數器和本身的局部變量,但再也不擁有系統資源,它與父進程的其餘線程共享該進程所擁有的所有資源。由於多個線程共享父進程裏的所有資源,所以編程更加方便;但必須更加當心,咱們必須確保線程不會妨礙同一進程裏的其餘線程。
線程的執行須要通過以下狀態:
新建線程new
就緒start()
運行
阻塞sleep()
死亡stop()
各狀態的轉換關係以下圖所示:
88.簡述synchronized和java . util .concurrent .locks .Lock的異同
答:主要相同點:Lock能完成synchronized所實現的全部功能。
主要不一樣點:Lock有比synchronized更精確的線程語義和更好的性能。Synchronized會自動釋放鎖,而Lock必定要求程序員手工釋放,而且必須在finally從句中釋放。Lock還有更強大的功能,它的tryLock方法能夠非阻塞方式去拿鎖。
Java代碼查錯部分
1.
abstract class Name {
private String name;
public abstract boolean isStupidName(String name) {}
}
答:錯。abstract方法必須以分號;結尾,並且不帶花括號{}
2.
public class Something {
void doSomething () {
privateString s = "";
int l = s.length();
}
}
有錯嗎?
答:錯。局部變量前不能放置任何修飾符(private,public,和protected),final能夠用來修飾局部變量。