這套面試題主要目的是幫助那些尚未java軟件開發實際工做經驗,而正在努力尋找java軟件開發工做的朋友在筆試時更好地贏得筆試和麪試。html
能夠有多個類,但只能有一個 public 的類,而且 public 的類名必須與文件名相一致。java
java 中的保留字,如今沒有在 java 中使用。程序員
& 和 && 均可以用做邏輯與的運算符,表示邏輯與( and ),當運算符兩邊的表達式的結果都爲 true 時,整個運算結果才爲 true ,不然,只要有一方爲 false ,則結果爲 false 。面試
&& 還具備短路的功能,即若是第一個表達式爲 false ,則再也不計算第二個表達式,例如,對於 if(str != null && !str.equals(「」)) 表達式,當 str 爲 null 時,後面的表達式不會執行,因此不會出現 NullPointerException 若是將 && 改成 & ,則會拋出 NullPointerException 異常。 If(x==33 & ++y>0) y 會增加, If(x==33 && ++y>0) 不會增加算法
& 還能夠用做位運算符,當 & 操做符兩邊的表達式不是 boolean 類型時, & 表示按位與操做,咱們一般使用 0x0f 來與一個整數進行 & 運算,來獲取該整數的最低 4 個 bit 位,例如, 0x31 & 0x0f 的結果爲 0x01 。sql
在 Java 中,要想跳出多重循環,能夠在外面的循環語句前定義一個標號,而後在裏層循環體的代碼中使用帶有標號的 break 語句,便可跳出外層循環。編程
在 switch ( expr1 )中, expr1 只能是一個整數表達式或者枚舉常量(更大字體),整數表達式能夠是 int 基本類型或 Integer 包裝類型,因爲, byte,short,char 均可以隱含轉換爲 int ,因此,這些類型以及這些類型的包裝類型也是能夠的。顯然, long 和 String 類型都不符合 switch 的語法規定,而且不能被隱式轉換成 int 類型,因此,它們不能做用於 swtich 語句中。數組
對於 short s1 = 1; s1 = s1 + 1; 因爲 s1+1 運算時會自動提高表達式的類型,因此結果是 int 型,再賦值給 short 類型 s1 時,編譯器將報告須要強制轉換類型的錯誤。安全
對於 short s1 = 1; s1 += 1; 因爲 += 是 java 語言規定的運算符, java 編譯器會對它進行特殊處理,所以能夠正確編譯。網絡
char 型變量是用來存儲 Unicode 編碼的字符的, unicode 編碼字符集中包含了漢字,因此, char 型變量中固然能夠存儲漢字啦。不過,若是某個特殊的漢字沒有被包含在 unicode 編碼字符集中,那麼,這個 char 型變量中就不能存儲這個特殊漢字。補充說明: unicode 編碼佔用兩個字節,因此, char 類型的變量也是佔用兩個字節。
2 << 3 ,
由於將一個數左移 n 位,就至關於乘以了 2 的 n 次方,那麼,一個數乘以 8 只要將其左移 3 位便可,而位運算 cpu 直接支持的,效率最高,因此, 2 乘以 8 等於幾的最效率的方法是 2 << 3 。
使用 final 關鍵字修飾一個變量時,是指引用變量不能變,引用變量所指向的對象中的內容仍是能夠改變的。
== 操做符專門用來比較兩個變量的值是否相等,也就是用於比較變量所對應的內存中所存儲的數值是否相同,要比較兩個基本類型的數據或兩個引用變量是否相等,只能用 == 操做符。
equals 方法是用於比較兩個獨立對象的內容是否相同,就比如去比較兩我的的長相是否相同,它比較的兩個對象是獨立的。
在語法定義上的區別:靜態變量前要加 static 關鍵字,而實例變量前則不加。
在程序運行時的區別:實例變量屬於某個對象的屬性,必須建立了實例對象,其中的實例變量纔會被分配空間,才能使用這個實例變量。靜態變量不屬於某個實例對象,而是屬於類,因此也稱爲類變量,只要程序加載了類的字節碼,不用建立任何實例對象,靜態變量就會被分配空間,靜態變量就能夠被使用了。總之,實例變量必須建立對象後才能夠經過這個對象來使用,靜態變量則能夠直接使用類名來引用。
不能夠。由於非 static 方法是要與對象關聯在一塊兒的,必須建立一個對象後,才能夠在該對象上進行方法調用,而 static 方法調用時不須要建立對象,能夠直接調用。也就是說,當一個 static方法被調用時,可能尚未建立任何實例對象,若是從一個 static 方法中發出對非 static 方法的調用,那個非 static 方法是關聯到哪一個對象上的呢?這個邏輯沒法成立,因此,一個 static 方法內部發出對非 static 方法的調用。
Integer 是 java 爲 int 提供的封裝類。 int 的默認值爲 0 ,而 Integer 的默認值爲 null ,即 Integer 能夠區分出未賦值和值爲 0 的區別, int 則沒法表達出未賦值的狀況。
Math 類中提供了三個與取整有關的方法: ceil 、 floor 、 round ,這些方法的做用與它們的英文名稱的含義相對應,例如, ceil 的英文意義是天花板,該方法就表示向上取整, Math.ceil(11.3) 的結果爲 12,Math.ceil(-11.3) 的結果是 -11 ; floor 的英文意義是地板,該方法就表示向下取整, Math.ceil(11.6) 的結果爲 11,Math.ceil(-11.6) 的結果是 -12 ;最難掌握的是 round 方法,它表示「四捨五入」,算法爲 Math.floor(x+0.5) ,即將原來的數字加上 0.5 後再向下取整,因此, Math.round(11.5) 的結果爲 12 , Math.round(-11.5) 的結果爲 -11 。
這四個做用域的可見範圍以下表所示。
說明:若是在修飾的元素上面沒有寫任何訪問修飾符,則表示 friendly 。
做用域 當前類 同一 package 子孫類 其餘 package
public √ √ √ √
protected √ √ √ ×
friendly √ √ × ×
private √ × × ×
Overload 是重載的意思, Override 是覆蓋的意思,也就是重寫。
重載 Overload 表示同一個類中能夠有多個名稱相同的方法,但這些方法的參數列表各不相同(即參數個數或類型不一樣)。
重寫 Override 表示子類中的方法能夠與父類中的某個方法的名稱和參數徹底相同,經過子類建立的實例對象調用這個方法時,將調用子類中的定義方法,這至關於把父類中定義的那個徹底相同的方法給覆蓋了,這也是面向對象編程的多態性的一種表現。
構造器 Constructor 不能被繼承,所以不能重寫 Override ,但能夠被重載 Overload 。
18 、接口是否可繼承接口 ? 抽象類是否可實現 (implements) 接口 ? 抽象類是否可繼承具體類 (concrete class)? 抽象類中是否能夠有靜態的 main 方法?
接口能夠繼承接口。抽象類能夠實現 (implements) 接口,抽象類是否可繼承具體類。抽象類中能夠有靜態的 main 方法。
clone 有缺省行爲, super.clone(); 由於首先要把父類中的成員複製到位,而後纔是複製本身的成員。
面向對象的編程語言有封裝、繼承 、抽象、多態等 4 個主要的特徵。
靠的是父類或接口定義的引用變量能夠指向子類或具體實現類的實例對象,而程序調用的方法在運行期才動態綁定,就是引用變量所指向的具體實例對象的方法,也就是內存里正在運行的那個對象的方法,而不是引用變量的類型中定義的方法。
含有 abstract 修飾符的 class 即爲抽象類, abstract 類不能建立的實例對象。含有 abstract 方法的類必須定義爲 abstract class , abstract class 類中的方法沒必要是抽象的。 abstract class 類中定義抽象方法必須在具體 (Concrete) 子類中實現,因此,不能有抽象構造方法或抽象靜態方法。若是的子類沒有實現抽象父類中的全部抽象方法,那麼子類也必須定義爲 abstract 類型。
接口( interface )能夠說成是抽象類的一種特例,接口中的全部方法都必須是抽象的。接口中的方法定義默認爲 public abstract 類型,接口中的成員變量類型默認爲 public static final 。
下面比較一下二者的語法區別:
1. 抽象類能夠有構造方法,接口中不能有構造方法。
2. 抽象類中能夠有普通成員變量,接口中沒有普通成員變量
3. 抽象類中能夠包含非抽象的普通方法,接口中的全部方法必須都是抽象的,不能有非抽象的普通方法。
4. 抽象類中的抽象方法的訪問類型能夠是 public , protected 和(默認類型 , 雖然
eclipse 下不報錯,但應該也不行),但接口中的抽象方法只能是 public 類型的,而且默認即爲public abstract 類型。
5. 抽象類中能夠包含靜態方法,接口中不能包含靜態方法
6. 抽象類和接口中均可以包含靜態成員變量,抽象類中的靜態成員變量的訪問類型能夠任意,但接口中定義的變量只能是 public static final 類型,而且默認即爲 public static final 類型。
7. 一個類能夠實現多個接口,但只能繼承一個抽象類。
abstract 的 method 不能夠是 static 的,由於抽象的方法是要被子類實現的,而 static 與子類扯不上關係!
native 方法表示該方法要用另一種依賴平臺的編程語言實現的,不存在着被子類實現的問題,因此,它也不能是抽象的,不能與 abstract 混用。
內部類就是在一個類的內部定義的類,內部類中不能定義靜態成員(靜態成員不是對象的特性,只是爲了找一個容身之處,因此須要放到一個類中而已。
25 、 Anonymous Inner Class ( 匿名內部類 ) 是否能夠 extends( 繼承 ) 其它類,是否能夠 implements( 實現 )interface( 接口 )?
能夠繼承其餘類或實現其餘接口。不只是能夠,而是必須 !
基本數據類型包括 byte 、 int 、 char 、 long 、 float 、 double 、 boolean 和 short 。
java.lang.String 類是 final 類型的,所以不能夠繼承這個類、不能修改這個類。爲了提升效率節省空間,咱們應該用 StringBuffer 類
27 、 String s = "Hello";s = s + " world!"; 這兩行代碼執行後,原始的 String 對象中的內容到底變了沒有?
沒有。由於 String 被設計成不可變 (immutable) 類,因此它的全部對象都是不可變對象。
String 類是 final 類故不能夠繼承。
兩個或一個, 」xyz」 對應一個對象,這個對象放在字符串常量緩衝區,常量 」xyz」 無論出現多少遍,都是緩衝區中的那一個。 New String 每寫一遍,就建立一個新的對象,它一句那個常量 」xyz」 對象的內容來建立出一個新 String 對象。若是之前就用過 ’xyz’ ,這句表明就不會建立 」xyz」 本身了,直接從緩衝區拿。
JAVA 平臺提供了兩個類: String 和 StringBuffer ,它們能夠儲存和操做字符串,即包含多個字符的字符數據。這個 String 類提供了數值不可改變的字符串。而這個 StringBuffer 類提供的字符串進行修改。
String 覆蓋了 equals 方法和 hashCode 方法,而 StringBuffer 沒有覆蓋 equals 方法和 hashCode 方法,因此,將 StringBuffer 對象存儲進 Java 集合類中時會出現問題。
數組沒有 length() 這個方法,有 length 的屬性。 String 有有 length() 這個方法。
final 用於聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。
finally 是異常處理語句結構的一部分,表示老是執行。
finalize 是 Object 類的一個方法,在垃圾收集器執行的時候會調用被回收對象的此方法,能夠覆蓋此方法提供垃圾收集時的其餘資源回收。
異常表示程序運行過程當中可能出現的非正常狀態,運行時異常表示虛擬機的一般操做中可能遇到的異常,是一種常見運行錯誤。 java 編譯器要求方法必須聲明拋出可能發生的非運行時異常,可是並不要求必須聲明拋出未被捕獲的運行時異常。
error 表示恢復不是不可能但很困難的狀況下的一種嚴重問題。好比說內存溢出。不可能期望程序能處理這樣的狀況。 exception 表示一種設計或實現問題。也就是說,它表示若是程序運行正常,從不會發生的狀況。
ClassCastException 類轉換異常, IllegalArgumentException 非法參數異常, IndexOutOfBoundsException 數組越界異常, NullPointerException 空指針異常, ArrayStoreException 數據存儲異常。
sleep 就是正在執行的線程主動讓出 cpu , cpu 去執行其餘線程,在 sleep 指定的時間事後, cpu 纔會回到這個線程上繼續往下執行,若是當前線程進入了同步鎖, sleep 方法並不會釋放鎖,即便當前線程使用 sleep 方法讓出了 cpu ,但其餘被同步鎖擋住了的線程也沒法獲得執行。 wait 是指在一個已經進入了同步鎖的線程內,讓本身暫時讓出同步鎖,以便其餘正在等待此鎖的線程能夠獲得同步鎖並運行,只有其餘線程調用了 notify 方法( notify 並不釋放鎖,只是告訴調用過 wait 方法的線程能夠去參與得到鎖的競爭了,但不是立刻獲得鎖,由於鎖還在別人手裏,別人還沒釋放。若是 notify 方法後面的代碼還有不少,須要這些代碼執行完後纔會釋放鎖,能夠在 notfiy方法後增長一個等待和一些代碼,看看效果),調用 wait 方法的線程就會解除 wait 狀態和程序能夠再次獲得鎖後繼續向下運行。
若是數據將在線程間共享。例如正在寫的數據之後可能被另外一個線程讀到,或者正在讀的數據可能已經被另外一個線程寫過了,那麼這些數據就是共享數據,必須進行同步存取。
當應用程序在對象上調用了一個須要花費很長時間來執行的方法,而且不但願讓程序等待方法的返回時,就應該使用異步編程,在不少狀況下采用異步途徑每每更有效率。
多線程有兩種實現方法,分別是繼承 Thread 類與實現 Runnable 接口
同步的實現方面有兩種,分別是 synchronized,wait 與 notify
wait(): 使一個線程處於等待狀態,而且釋放所持有的對象的 lock 。
sleep(): 使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要捕捉 InterruptedException 異常。
notify(): 喚醒一個處於等待狀態的線程,注意的是在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由 JVM 肯定喚醒哪一個線程,並且不是按優先級。
Allnotity(): 喚醒全部處入等待狀態的線程,注意並非給全部喚醒線程一個對象的鎖,而是讓它們競爭。
啓動一個線程是調用 start() 方法,使線程就緒狀態,之後能夠被調度爲運行狀態,一個線程必須關聯一些具體的執行代碼, run() 方法是該線程所關聯的執行代碼。
分幾種狀況:
1. 其餘方法前是否加了 synchronized 關鍵字,若是沒加,則能。
2. 若是這個方法內部調用了 wait ,則能夠進入其餘 synchronized 方法。
3. 若是其餘個方法都加了 synchronized 關鍵字,而且內部沒有調用 wait ,則不能。
4. 若是其餘方法是 static ,它用的同步鎖是當前類的字節碼,與非靜態的方法不能同步,由於非靜態的方法用的是 this 。
一個程序中能夠有多條執行線索同時執行,一個線程就是程序中的一條執行線索,每一個線程上都關聯有要執行的代碼。
狀態:就緒,運行, synchronize 阻塞, wait 和 sleep 掛起,結束。 wait 必須在 synchronized內部調用。
主要相同點: Lock 能完成 synchronized 所實現的全部功能
主要不一樣點: Lock 有比 synchronized 更精確的線程語義和更好的性能。
synchronized 會自動釋放鎖,而 Lock 必定要求程序員手工釋放,而且必須在 finally 從句中釋放。
答:參考 https://www.cnblogs.com/bingyimeiling/p/10255037.html
comparable/comparator
( 1 )同步性:
Vector 是線程安全的,也就是說是它的方法之間是線程同步的,而 ArrayList 是線程序不安全的,它的方法之間是線程不一樣步的。若是隻有一個線程會訪問到集合,那最好是使用 ArrayList ,由於它不考慮線程安全,效率會高些;若是有多個線程會訪問到集合,那最好是使用 Vector ,由於不須要咱們本身再去考慮和編寫線程安全的代碼。
( 2 )數據增加:
ArrayList 與 Vector 都有一個初始的容量大小,當存儲進它們裏面的元素的個數超過了容量時,就須要增長 ArrayList 與 Vector 的存儲空間,每次要增長存儲空間時,不是隻增長一個存儲單元,而是增長多個存儲單元,每次增長的存儲單元的個數在內存空間利用與程序效率之間要取得必定的平衡。 Vector 默認增加爲原來兩倍,而 ArrayList 的增加策略在文檔中沒有明確規定(從源代碼看到的是增加爲原來的 1.5 倍)。 ArrayList 與 Vector 均可以設置初始的空間大小, Vector 還能夠設置增加的空間大小,而 ArrayList 沒有提供設置增加空間的方法。
總結:即 Vector 增加原來的一倍, ArrayList 增長原來的 0.5 倍。
一 . 歷史緣由 :Hashtable 是基於陳舊的 Dictionary 類的, HashMap 是 Java 1.2 引進的 Map 接口的一個實現
二 . 同步性 :Hashtable 是線程安全的,也就是說是同步的,而 HashMap 是線程序不安全的,不是同步的
三 . 值:只有 HashMap 可讓你將空值做爲一個表的條目的 key 或 value
一個是存儲單列數據的集合,另外一個是存儲鍵和值這樣的雙列數據的集合, List 中存儲的數據是有順序,而且容許重複; Map 中存儲的數據是沒有順序的,其鍵是不能重複的,它的值是能夠有重複的。
List , Set 是, Map 不是
ArrayList 和 Vector 都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增長和插入元素,它們都容許直接按序號索引元素,可是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢, Vector 因爲使用了 synchronized 方法(線程安全),一般性能上較 ArrayList 差,而 LinkedList 使用雙向鏈表實現存儲,按序號索引數據須要進行前向或後向遍歷,可是插入數據時只須要記錄本項的先後項便可,因此插入速度較快。
LinkedList 也是線程不安全的, LinkedList 提供了一些方法,使得 LinkedList 能夠被看成堆棧和隊列來使用。
Collection 是集合類的上級接口,繼承與他的接口主要有 Set 和 List.
Collections 是針對集合類的一個幫助類,他提供一系列靜態方法實現對各類集合的搜索、排序、線程安全化等操做。
經常使用的類:Date,System,List,HashMap , String , Integer
經常使用的包: java.lang ,java.io, java.util, java.sql,javax.servlet
經常使用的接口: List, Map ,Document,NodeList ,Servlet,HttpServletRequest,HttpServletResponse
52 、 java 中有幾種類型的流? JDK 爲每種類型的流提供了一些抽象類以供繼承,請說出他們分別是哪些類?
字節流,字符流。字節流繼承於 InputStream OutputStream ,字符流繼承於 InputStreamReader OutputStreamWriter 。
在此我向你們推薦一個架構學習交流裙。交流學習裙號:687810532,裏面會分享一些資深架構師錄製的視頻錄像
咱們有時候將一個 java 對象變成字節流的形式傳出去或者從一個字節流中恢復成一個 java 對象,例如,要將 java 對象存儲到硬盤或者傳送給網絡上的其餘計算機,這個過程咱們能夠本身寫代碼去把一個 java 對象變成某個格式的字節流再傳輸,可是, jre 自己就提供了這種支持,咱們能夠調用 OutputStream 的 writeObject 方法來作,若是要讓 java 幫咱們作,要被傳輸的對象必須實現 serializable 接口,這樣, javac 編譯時就會進行特殊處理,編譯的類才能夠被 writeObject 方法操做,這就是所謂的序列化。須要被序列化的類必須實現 Serializable 接口,該接口是一個 mini 接口,其中沒有須要實現的方法, implements Serializable 只是爲了標註該對象是可被序列化的。
java 的內存分爲兩類,一類是棧內存,一類是堆內存。棧內存是指程序進入一個方法時,會爲這個方法單獨分配一塊私屬存儲空間,用於存儲這個方法內部的局部變量,當這個方法結束時,分配給這個方法的棧會釋放,這個棧中的變量也將隨之釋放。
堆是與棧做用不一樣的內存,通常用於存放不放在當前方法棧中的那些數據,例如,使用 new 建立的對象都放在堆裏,因此,它不會隨方法的結束而消失。方法中的局部變量使用 final 修飾後,放在堆中,而不是棧中。
GC 是垃圾收集的意思( Gabage Collection ) , 內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰, Java 提供的 GC 功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的, Java 語言沒有提供釋放已分配內存的顯示操做方法。