1.1 簡述static和final的用法?
static:修飾屬性,方法,代碼塊
(1)靜態屬性:也可叫類變量 類名.屬性名 來訪問
(共有的類變量與對象無關,只和類有關)
注意:類中的實例變量是在創建對象時被初始化的,被static修飾的屬性,也就是類變量,是在類加載時被創建並進行初始化,類加載的過程是進行一次。也就是類變量只會被創建一次。
(2)靜態方法:類名.方法名 直接訪問
注意:static修飾的方法,不能直接訪問本類中的非靜態(static)成員(包括方法和屬性)
本類的非靜態方法可以訪問本類的靜態成員(包括方法和屬性),可以調用靜態方法。
修飾變量,方法,類
final:修飾變量,類,方法
(1)修飾變量
被fianl修飾的成員變量就是常量(常量名大寫),一旦賦值不能改變
修飾局部變量:修飾基本數據類型 -> 變量的值不能改變
修飾引用 -> 引用只能指向固定的對象
修飾實例變量:默認值不生效,可以再賦值
(2)修飾方法 :不能被子類覆蓋
(3)修飾類:不能被繼承
在一個final類中的所有方法,默認都是final的
注意:final,不能用來修飾構造方法。
1.2 寫出冒泡排序的算法
for (int i=0;i<arr.length-1;i++){ //控制輪數 for (int j=0;j<arr.length-1-i;j++){ //控制每一輪的次數 if(arr[j]>arr[j+1]){ //每次都是和它下一個元素比 int t=arr[j]; arr[j]=arr[j+1]; arr[j+1]=t; } } }
1.3 abstract class 和 interface 有什么區別?
|
abstract class |
interface |
實例化 |
不能 |
不能 |
類 |
一種繼承關系,一個類只能使用一次繼承關系。可以通過實現多個接口 |
一個類可以實現多個interface |
數據成員 |
可有自己的 |
靜態的不能被修改即必須是static final,一般不在此定義 |
方法 |
可以私有的,非abstract方法,必須實現 |
不能有私有的,默認是public,abstract 類型 |
變量 |
可有私有的,變量有默認的類型,其值可以在子類中重新定義,也可以重新賦值 |
不可有私有的,默認是public static final 型,且必須給其初值,實現類中不能重新定義,不能改變其值。 |
設計理念 |
表示的是“is-a”關系 |
表示的是“like-a”關系 |
實現 |
需要繼承,要用extends |
要用implements |
1.相同點
A. 兩者都是抽象類,都不能實例化。
B. interface實現類及abstrct class的子類都必須要實現已經聲明的抽象方法。
2. 不同點
A. interface需要實現,要用implements,而abstract class需要繼承,要用extends。
B. 一個類可以實現多個interface,但一個類只能繼承一個abstract class。
C. interface強調特定功能的實現,而abstract class強調所屬關系。
D. 盡管interface實現類及abstrct class的子類都必須要實現相應的抽象方法,但實現的形式不同。interface中的每一個方法都是抽象方法,都只是聲明的 (declaration, 沒有方法體),實現類必須要實現。而abstract class的子類可以有選擇地實現。
1.4 類有哪三個基本特性?各特性的優點?
類具有封裝性、繼承性和多態性。
封裝性:類的封裝性為類的成員提供公有、缺省、保護和私有等訪問權限,目的是隱藏類中的私有變量和類中方法的實現細節。
繼承性:允許通過繼承原有類的某些特性或全部特性而產生全新的類,原有的類稱為父類,產生的新類稱為子類。子類不僅可以直接繼承父類的共性,而且也可以創建它特有的個性。
多態性:是指在基類中定義的屬性和方法被子類繼承之后,可以具有不同的數據類型或表現出不同行為,多態性有兩種表現形式:重載和覆蓋。
1.5 Error和Exception有什么區別? 列出你見過的Exception並簡要說明
答:error表示系統級的錯誤和程序不必處理的異常,
是恢復不是不可能但很困難的情況下的一種嚴重問題;
比如內存溢出,不可能指望程序能處理這樣的情況;
exception表示需要捕捉或者需要程序進行處理的異常,
是一種設計或實現問題;也就是說,它表示如果程序運行正常,
從不會發生的情況。 常見異常有: NullPointerException:
當操作一個空引用時會出現此錯誤。 NumberFormatException:
數據格式轉換出現問題時出現此異常。 ClassCastException:
強制類型轉換類型不匹配時出現此異常。 ArrayIndexOutOfBoundsException:
數組下標越界,當使用一個不存在的數組下標時出現此異常。
1.6 java中會存在內存泄露嗎?請簡單描述。
答:Java存在內存泄露。
內存泄露是指系統中存在無法回收的內存,有時候會造成內存不足或系統崩潰。
Java中的內存泄露當然是指:存在無用但是垃圾回收器無法回收的對象。
而且即使有內存泄露問題存在,也不一定會表現出來。
自己實現堆棧的數據結構時有可能會出現內存泄露。
1.7 多線程有幾種實現方法,都是什么?同步有幾種實現方法,都是什么?
答:多線程有兩種實現方法:繼承Thread類或者實現Runnable接口。
實現同步也有兩種方法:一種是同步方法,另一種是同步代碼塊。
同步方法是在方法返回類型前面加上synchronized關鍵字
同步代碼塊是synchronized (這里寫需要同步的對象){...}
1.8 .sleep()和wait()有什么區別?
不同點:
1. Thread類的方法:sleep(),yield()等
Object的方法:wait()和notify()等
2.每個對象都有一個鎖來控制同步訪問。Synchronized關鍵字可以和對象的鎖交互,來實現線程的同步。
sleep方法沒有釋放鎖,wait方法釋放了鎖,使得其他線程可以使用同步控制塊或者方法。
3.wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用
4.sleep必須捕獲異常,而wait,notify和notifyAll不需要捕獲異常
1.9 談談java跟你所知道的其它的語言相比,有什么優點??
Java是一種可以撰寫跨平台應用程序的面向對象的程序設計語言。Java技術具有卓越的通用性、高效性、平台移植性和安全性,廣泛應用於PC、數據中心、游戲控制台、科學超級計算機、移動電話和互聯網,同時擁有全球最大的開發者專業社群。
Java是功能完善的通用程序設計語言,可以用來開發可靠的、要求嚴格的應用程序。
java是純面向對象開發,功能強大,分支眾多,沒有java不能做的軟件。C/S也好B/S也好。從功能上講,沒有語言可以和java相比。
C是面向過程編程的,這樣往往會導致所謂的單一程序,既所有的功能只能包含在幾個(通常是一個)代碼模塊中。當然,C語言也有自身的不足,比如:C語言的語法限制不太嚴格,對變量的類型約束不嚴格,影響程序的安全性,對數族下標越界不作檢查等。從應用的角度,C語言比其他高級語言較難掌握。
1.10 談談你對面向對象的理解??
所謂的面向對象就是將我們的程序模塊化,對象化,把具體事物的特性屬性和通過這些屬性來實現一些動作的具體方法放到一個類里面,這就是封裝。封裝是我們所說的面相對象編程的特征之一。除此之外還有繼承和多態。繼承有點類似與我們生物學上的遺傳,就是子類的一些特征是來源於父類的,兒子遺傳了父親或母親的一些性格,或者相貌,又或者是運動天賦。有點種瓜得瓜種豆得豆的意思。面向對象里的繼承也就是父類的相關的屬性,可以被子類重復使用,子類不必再在自己的類里面重新定義一回,父類里有點我們只要拿過來用就好了。而對於自己類里面需要用到的新的屬性和方法,子類就可以自己來擴展了。當然,會出現一些特殊情況,就是我們在有一些方法在父類已經定義好了,但是子類我們自己再用的時候,發現,其實,我們的雖然都是計算工資的,但是普通員工的工資計算方法跟經理的計算方法是不一樣的,所以這個時候,我們就不能直接調用父類的這個計算工資的方法了。這個時候我們就需要用到面向對象的另一個特性,多態。對,就是多態,我們要在子類里面把父類里面定義計算工資的方法在子類里面重新實現一遍。多態包含了重載和重寫。重寫很簡單就是把子類從父親類里繼承下來的方法重新寫一遍,這樣,父類里相同的方法就被覆蓋了,當然啦,你還是可以通過super.CaculSalary方法來調用父類的工資計算方法。而重載就是類里面相同方法名,不同形參的情況,可以是形參類型不同或者形參個數不同,或者形參順序不同,但是不能使返回值類型不同。
1.11 簡單講一下java的跨平台原理
java源程序(.java文件)通過編譯器編譯成為Class文件(字節碼文件),而它的class文件是基於字節碼(以byte為單位存儲的文件)的,而字節碼文件是描述程序要運行的的虛指令的集合,這些虛指令的集合與任何的平台無關,Java虛擬機認識它(只要在不同的平台下部署相應的jre,運行jvm!就可以了)
1.12 有了基本數據類型,為什么還需要包裝類型?
我們知道Java是一個面相對象的編程語言,基本類型並不具有對象的性質,為了讓基本類型也具有對象的特征,就出現了包裝類型(如我們在使用集合類型Collection時就一定要使用包裝類型而非基本類型),它相當於將基本類型“包裝起來”,使得它具有了對象的性質,並且為其添加了屬性和方法,豐富了基本類型的操作。
另外,當需要往ArrayList,HashMap中放東西時,像int,double這種基本類型是放不進去的,因為容器都是裝object的,這是就需要這些基本類型的包裝器類了。
1.13 說一下"=="和equals方法究竟有什么區別?
==操作符專門用來比較兩個變量的值是否相等,也就是用於比較變量所對應的內存中所存儲的數值是否相同,要比較兩個基本類型的數據或兩個引用變量是否相等,只能用==操作符。
equals 方法是用於比較兩個獨立對象的內容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個對象是獨立的。
1.14 講一下java中的集合
set(集)、list(列表)和map(映射)。
區別嘛 HASHMAP只有KEY和value值對應的。。set是可以自動清楚相同的元素
list是其對象以線性方式存儲,沒有特定順序,只有一個開頭和一個結尾,當然,它與根本沒有順序的集是不同的。
列表在數據結構中分別表現為:數組和向量、鏈表、堆棧、隊列。
1.15 ArrayList和LinkedList的區別?
1.ArrayList是實現了基於動態數組的數據結構,LinkedList基於鏈表的數據結構。
2.對於隨機訪問get和set,ArrayList覺得優於LinkedList,因為LinkedList要移動指針。
3.對於新增和刪除操作add和remove,LinedList比較占優勢,因為ArrayList要移動數據。
1.16 講一下HashMap和HashTable的區別?
在Java 2以前,一般使用Hashtable來映射鍵值和元素。為了使用Java集合框架,Java對Hashtable進行了重新設計,但是,為了向后兼容保留了所有的方法。Hashtable實現了Map接口,除了Hashtable具有同步功能之外,它與HashMap的用法是一樣的。·
在使用時一般是用ArrayList代替Vector,LinkedList代替Stack,HashMap代替HashTable,即使在多線程中需要同步,也是用同步包裝類。
1.17 請說出集合類中List、Map、Set的區別
答:List和Set繼承了Collection接口,而map不是;
List中存放元素有順序並且可以重復;
set中存放的元素是無序並且是不可能重復的;
Map中存放是鍵值對。
1.18 Collection 和 Collections的區別?
答:Collection是java.util下的接口,它是各種集合的父接口,
繼承於它的接口主要有Set 和List;Collections是個java.util下的類,
是針對集合的幫助類,提供一系列靜態方法實現對各種集合的搜索、排序、線程安全化等操作。
HashSet :內部封裝了HashMap和TreeMap,數據保存在鍵這一列
LinkedHashMap(哈希表,存放數據以鏈表來連接,數組存放無序但鏈表連接有序,可看做一個有序的HashMap),既可快速定位,查找數據,又可以使數據存放有序
ConcurrentHashMap(分段加鎖)Concurrent-同步
1.19 String、StringBuffer和StringBuilder的區別?
- 首先說運行速度,或者說是執行速度,在這方面運行速度快慢為:StringBuilder > StringBuffer > String
2. 再來說線程安全
在線程安全上,StringBuilder是線程不安全的,而StringBuffer是線程安全的
String:適用於少量的字符串操作的情況
StringBuilder:適用於單線程下在字符緩沖區進行大量操作的情況
StringBuffer:適用多線程下在字符緩沖區進行大量操作的情況
1.20 講一下線程的幾種實現方式?
extends Thread
implements Runnable
implements Callable
Runnable和Callable的區別是,
(1)Callable規定的方法是call(),Runnable規定的方法是run()。
(2)Callable的任務執行后可返回值,而Runnable的任務是不能返回值得
(3)call方法可以拋出異常,run方法不可以
(4)運行Callable任務可以拿到一個Future對象,表示異步計算的結果。
1.21 講一下線程的幾種啟動方式?
第一種方法是將類聲明為 Thread 的子類。該子類應重寫 Thread 類的 run 方法,然后在run方法里填寫相應的邏輯代碼。
第二種方法是實現Runnable接口,並編寫run方法,相比繼承Thread類創建線程的好處是以實現接口的方式創建線程可以對類進行更好的擴展,該類可以繼承其他類來擴展自身需求,相比第一種方式更加靈活,擴展性強。
實現Callable接口創建線程與Runnable接口的不同之處在於:如果你想要在線程執行完畢之后得到帶有返回值的線程則實現Callable接口
1.22 有沒有使用過線程並發庫?
在java5之后,就有了線程池的功能了,在介紹線程池之前,先來簡單看一下線程池的概念。假設我開了家咨詢公司,那么每天會有很多人過來咨詢問題,如果我一個個接待的話,必然有很多人要排隊,這樣效率就很差,我想解決這個問題,現在我雇幾個客服,來了一個咨詢的,我就分配一個客服去接待他,再來一個,我再分配個客服去接待……如果第一個客服接待完了,我就讓她接待下一個咨詢者,這樣我雇的這些客服可以循環利用。這些客服就好比不同的線程,那么裝這些線程的容器就稱為線程池。
1.23 靜態變量和實例變量的區別?
靜態變量也叫類變量,這種變量前加了static修飾符。可以直接用類名調用,也可以用對象調用,而且所有對象的同一個類變量 都是共享同一塊內存空間。
實例變量也叫對象變量,這種變量沒有加static修飾符。只能通過對象調用, 而且所有對象的同一個實例變量是共享不同的內存空間的。
區別在於:
靜態變量是所有對象共有的,某一個對象將它的值改變了,其他對象再去獲取它的值,得到的是改變后的值;
實例變量則是每一個對象私有的,某一個對象將它的值改變了,不影響其他對象取值的結果,其他對象仍會得到實例變量一開始就被賦予的值。
1.24 try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后?
會執行 try{}中的return執行后在沒有返回數據時先去執行finally{}中的代碼,然后再返回。所以說finally{}在return中間執行
1.25 同步和異步有何異同,在什么情況下分別使用他們?舉例說明。
如果數據將在線程間共享.例如正在寫的數據以后可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那么這些數據就是共享數據,必須進行同步存取.
當應用程序在對象上調用了一個需要花費很長時間來執行的方法,並且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率.
1.26 java 中有幾種類型的流?JDK 為每種類型的流提供了一些抽象類以供繼承, 請說出他們分別是哪些類?
Java中的流分為兩種,一種是字節流,另一種是字符流,分別由四個抽象類來表示(每種流包括輸入和輸出兩種所以一共四個):InputStream,OutputStream,Reader,Writer。Java中其他多種多樣變化的流均是由它們派生出來的.
1.27 &和&&的區別?
&和&&都可以用作邏輯運算符,表示邏輯與。當運算符兩邊的表達式都為true時,結果才為true;否則,結果為false。
另外&&還具有短路功能,也就是說,當&&左邊的表達式結果為false時,將不再運算&&右邊的表達式,結果肯定為false。例如,對於if(str!=null&&!str.equals(“”)),當str為null時,不會對&&右邊的表達式進行運算,否則會出現空指針異常。
&還可以用作位運算符,當&兩邊的表達式不是boolean類型時,&表示按位與。
1.28 數組有沒有length()這個方法? String有沒有length()這個方法?
數組中沒有length()這個方法,但是數組中有length這個屬性。用來表示數組的長度。
String中有length()這個方法。用來得到字符串的長度。
1.29 構造器Constructor是否可被override?
構造器Constructor不能被繼承,因此不能重寫Override,但可以被重載Overload。
Constructor不能被繼承,所以Constructor也就不能被override。每一個類必須有自己的構造函數,負責構造自己這部分的構造。子類不會覆蓋父類的構造函數,相反必須負責在一開始調用父類的構造函數。
1.30 構造器如何工作?
Java在構造實例時的順序是這樣的:
1、分配對象空間,並將對象中成員初始化為0或者空,java不允許用戶操縱一個不定值的對象。
2、執行屬性值的顯式初始化
3、執行構造器
4 、將變量關聯到堆中的對象上
1.31 super與this的區別?
不同點:
1、super()主要是對父類構造函數的調用,this()是對重載構造函數的調用
2、super()主要是在繼承了父類的子類的構造函數中使用,是在不同類中的使用;this()主要是在同一類的不同構造函數中的使用
相同點:
1、super()和this()都必須在構造函數的第一行進行調用,否則就是錯誤的
1.32 GC是什么? 為什么要有GC?
GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,
忘記或者錯誤的內存回收會導致程序或系統的不穩定甚至崩潰,Java提供的GC功能可以自動監測對象是否超過作用域從而達到自動回收內存的目的,
Java語言沒有提供釋放已分配內存的顯示操作方法。Java程序員不用擔心內存管理,因為垃圾收集器會自動進行管理。要請求垃圾收集,可以調用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),但JVM可以屏蔽掉顯示的垃圾回收調用。
垃圾回收可以有效的防止內存泄露,有效的使用可以使用的內存。垃圾回收器通常是作為一個單獨的低優先級的線程運行,不可預知的情況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個對象或所有對象進行垃圾回收。
在Java誕生初期,垃圾回收是Java最大的亮點之一,因為服務器端的編程需要有效的防止內存泄露問題,然而時過境遷,如今Java的垃圾回收機制已經成為被詬病的東西。移動智能終端用戶通常覺得iOS的系統比Android系統有更好的用戶體驗,其中一個深層次的原因就在於Android系統中垃圾回收的不可預知性。
1.33 接口是否可繼承接口? 抽象類是否可實現(implements)接口? 抽象類是否可繼承實體類?
接口可以繼承接口。抽象類可以實現(implements)接口,抽象類可繼承實體類,但前提是實體類必須有明確的構造函數
1.34 內部類可以引用他包含類的成員嗎?有沒有什么限制?
完全可以。如果不是靜態內部類,那沒有什么限制!
如果你把靜態嵌套類當作內部類的一種特例,那在這種情況下不可以訪問外部類的普通成員變量,而只能訪問外部類中的靜態成員
1.35 Java有沒有goto?
答:goto 是Java中的保留字,在目前版本的Java中沒有使用。(根據James Gosling(Java之父)編寫的《The Java Programming Language》一書的附錄中給出了一個Java關鍵字列表,其中有goto和const,但是這兩個是目前無法使用的關鍵字,因此有些地方將其稱之為保留字,其實保留字這個詞應該有更廣泛的意義,因為熟悉C語言的程序員都知道,在系統類庫中使用過的有特殊意義的單詞或單詞的組合都被視為保留字)
1.36 解釋內存中的棧(stack)、堆(heap)和靜態區(static area)的用法
答:通常我們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用內存中的棧空間;而通過new關鍵字和構造器創建的對象放在堆空間;程序中的字面量(literal)如直接書寫的100、”hello”和常量都是放在靜態區中。棧空間操作起來最快但是棧很小,通常大量的對象都是放在堆空間,理論上整個內存沒有被其他進程使用的空間甚至硬盤上的虛擬內存都可以被當成堆空間來使用。
1.37 用最有效率的方法計算2乘以8?
答: 2 << 3(左移3位相當於乘以2的3次方,右移3位相當於除以2的3次方)。
1.38 在Java中,如何跳出當前的多重嵌套循環?
答:在最外層循環前加一個標記如A,然后用break A;可以跳出多重循環。(Java中支持帶標簽的break和continue語句,作用有點類似於C和C++中的goto語句,但是就像要避免使用goto一樣,應該避免使用帶標簽的break和continue,因為它不會讓你的程序變得更優雅,很多時候甚至有相反的作用,所以這種語法其實不知道更好)
1.39 兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對?
答:不對,如果兩個對象x和y滿足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:(1)如果兩個對象相同(equals方法返回true),那么它們的hashCode值一定要相同;(2)如果兩個對象的hashCode相同,它們並不一定相同。當然,你未必要按照要求去做,但是如果你違背了上述原則就會發現在使用容器時,相同的對象可以出現在Set集合中,同時增加新元素的效率會大大下降(對於使用哈希存儲的系統,如果哈希碼頻繁的沖突將會造成存取性能急劇下降)。
1.40 char 型變量中能不能存貯一個中文漢字,為什么?
答:char類型可以存儲一個中文漢字,因為Java中使用的編碼是Unicode(不選擇任何特定的編碼,直接使用字符在字符集中的編號,這是統一的唯一方法),一個char類型占2個字節(16比特),所以放一個中文是沒問題的。
1.41 Anonymous Inner Class(匿名內部類)是否可以繼承其它類?是否可以實現接口?
答:可以繼承其他類或實現其他接口,在Swing編程和Android開發中常用此方式來實現事件監聽和回調。
1.42 內部類可以引用它的包含類(外部類)的成員嗎?有沒有什么限制?
答:一個內部類對象可以訪問創建它的外部類對象的成員,包括私有成員。
1.43 Java 中的final關鍵字有哪些用法?
答:(1)修飾類:表示該類不能被繼承;(2)修飾方法:表示方法不能被重寫;(3)修飾變量:表示變量只能一次賦值以后值不能被修改(常量)。
1.44 寫出常見的5個RuntimeException
(1)java.lang.NullPointerException空指針異常,出現原因:調用了未經初始化的對象或者不存在的對象。
(2)ClassNoFoundException 指定類找不到,出現原因:類的名稱和路徑加載錯誤,通常是試圖通過字符串來加載某個類時可能引發異常。
(3)NumberFormatException字符串轉換為數字異常,出現原因:字符串數據中包含非數字型字符。
(4)IndexOutOfBoundsException數組下標越界異常
(5)IllegalArgumentException 方法傳遞參數錯誤
(6)ClassCastException數據類型轉換異常
(7)NoClassDefFoundExcetion 未找到類定義錯誤
(8)SQLException SQL異常
(9)InstantiationException實例化異常
(10)NoSuchMethodExceptioin 方法不存在異常
1.45 闡述final、finally、finalize的區別。
答:
- final:修飾符(關鍵字)有三種用法:如果一個類被聲明為final,意味着它不能再派生出新的子類,即不能被繼承,因此它和abstract是反義詞。將變量聲明為final,可以保證它們在使用中不被改變,被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取不可修改。被聲明為final的方法也同樣只能使用,不能在子類中被重寫。
- finally:通常放在try…catch…的后面構造總是執行代碼塊,這就意味着程序無論正常執行還是發生異常,這里的代碼只要JVM不關閉都能執行,可以將釋放外部資源的代碼寫在finally塊中。
- finalize:Object類中定義的方法,Java中允許使用finalize()方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在銷毀對象時調用的,通過重寫finalize()方法可以整理系統資源或者執行其他清理工作。
1.46 闡述ArrayList、Vector、LinkedList的存儲性能和特性。
答:ArrayList 和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增加和插入元素,它們都允許直接按序號索引元素,但是插入元素要涉及數組元素移動等內存操作,所以索引數據快而插入數據慢,Vector中的方法由於添加了synchronized修飾,因此Vector是線程安全的容器,但性能上較ArrayList差,因此已經是Java中的遺留容器。LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元通過附加的引用關聯起來,形成一個可以按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據需要進行前向或后向遍歷,但是插入數據時只需要記錄本項的前后項即可,所以插入速度較快。Vector屬於遺留容器(Java早期的版本中提供的容器,除此之外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,但是由於ArrayList和LinkedListed都是非線程安全的,如果遇到多個線程操作同一個容器的場景,則可以通過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器后再使用(這是對裝潢模式的應用,將已有對象傳入另一個類的構造器中創建新的對象來增強實現)。
1.47 Collection和Collections的區別?
答:Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操作,這些方法包括對容器的搜索、排序、線程安全化等等。
1.48 List、Map、Set三個接口存取元素時,各有什么特點?
答:List以特定索引來存取元素,可以有重復元素。Set不能存放重復元素(用對象的equals()方法來區分元素是否重復)。Map保存鍵值對(key-value pair)映射,映射關系可以是一對一或多對一。Set和Map容器都有基於哈希存儲和排序樹的兩種實現版本,基於哈希存儲的版本理論存取時間復雜度為O(1),而基於排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。
1.49 當一個線程進入一個對象的synchronized方法A之后,其它線程是否可進入此對象的synchronized方法B?
答:不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。因為非靜態方法上的synchronized修飾符要求執行方法時要獲得對象的鎖,如果已經進入A方法說明對象鎖已經被取走,那么試圖進入B方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。
1.50 請說出與線程同步以及線程調度相關的方法。
答:
- wait():使一個線程處於等待(阻塞)狀態,並且釋放所持有的對象的鎖;
- sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;
- notify():喚醒一個處於等待狀態的線程,當然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM確定喚醒哪個線程,而且與優先級無關;
- notityAll():喚醒所有處於等待狀態的線程,該方法並不是將對象的鎖給所有線程,而是讓它們競爭,只有獲得鎖的線程才能進入就緒狀態;
1.51 Java中如何實現序列化,有什么意義?
答:序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。可以對流化后的對象進行讀寫操作,也可將流化后的對象傳輸於網絡之間。序列化是為了解決對象流讀寫操作時可能引發的問題(如果不進行序列化可能會存在數據亂序的問題)。
要實現序列化,需要讓一個類實現Serializable接口,該接口是一個標識性接口,標注該類對象是可被序列化的,然后使用一個輸出流來構造一個對象輸出流並通過writeObject(Object)方法就可以將實現對象寫出(即保存其狀態);如果需要反序列化則可以用一個輸入流建立對象輸入流,然后通過readObject方法從流中讀取對象。序列化除了能夠實現對象的持久化之外,還能夠用於對象的深度克隆.
1.52 如何通過反射創建對象?
- 方法1:通過類對象調用newInstance()方法,例如:String.class.newInstance()
- 方法2:通過類對象的getConstructor()或getDeclaredConstructor()方法獲得構造器(Constructor)對象並調用其newInstance()方法創建對象,例如:String.class.getConstructor(String.class).newInstance(“Hello”);
1.53 談談 JVM 的內存結構和內存分配?
Java 內存模型
Java 虛擬機將其管轄的內存大致分三個邏輯部分:方法區(Method Area)、 Java 棧和 Java 堆。
1、方法區是靜態分配的,編譯器將變量綁定在某個存儲位置上,而且這些綁定不會在運行時改變。常數池,源代碼中的命名常量、 String 常量和 static 變量保存在方法區。
2、 Java Stack 是一個邏輯概念,特點是后進先出。一個棧的空間可能是連續的,也可能是不連續的。最典型的 Stack 應用是方法的調用, Java 虛擬機每調用一次方法就創建一個方法幀(frame),退出該
方法則對應的 方法幀被彈出(pop)。棧中存儲的數據也是運行時確定的。
3、 Java 堆分配(heap allocation)意味着以隨意的順序,在運行時進行存儲空間分配和收回的內存管理模型。堆中存儲的數據常常是大小、數量和生命期在編譯時無法確定的。 Java 對象的內存總是在 heap 中分配。
b) java 內存分配
1、基礎數據類型直接在棧空間分配;
2、方法的形式參數,直接在棧空間分配,當方法調用完成后從棧空間回收;
3、引用數據類型,需要用 new 來創建,既在棧空間分配一個地址空間,又在堆空間分配對象的類變量;
4、方法的引用參數,在棧空間分配一個地址空間,並指向堆空間的對象區,當方法調用完后從棧空間回收;
5、局部變量 new 出來時,在棧空間和堆空間中分配空間,當局部變量生命周期結束后,棧空間立刻被回收,堆空間區域等待 GC 回收;
6、方法調用時傳入的實際參數,先在棧空間分配,在方法調用完成后從棧空間釋放;
7、字符串常量在 DATA 區域分配 , this 在堆空間分配;
8、數組既在棧空間分配數組名稱, 又在堆空間分配數組實際的大小。
1.54 什么是雙親委派機制
雙親委派模式的工作原理的是;如果一個類加載器收到了類加載請求,它並不會自己先去加載,而是把這個請求委托給父類的加載器去執行,如果父類加載器還存在其父類加載器,則進一步向上委托,依次遞歸,請求最終將到達頂層的啟動類加載器,如果父類加載器可以完成類加載任務,就成功返回,倘若父類加載器無法完成此加載任務,子加載器才會嘗試自己去加載,這就是雙親委派模式,即每個兒子都不願意干活,每次有活就丟給父親去干,直到父親說這件事我也干不了時,兒子自己想辦法去完成,這不就是傳說中的雙親委派模式.那么這種模式有什么作用呢?
1.55 Static 關鍵字有哪些作用?
Static 有兩種作用: 第一, 為某特定數據類型或對象分配單一的存儲空間,而與創建對象的個數無關。 第二, 實現某個方法或屬性與類而不是對象關聯在一起。 Static 主要是有 4 種使用情況: Static 修飾成員變量:用 static 修飾的變量稱之為靜態變量或者也叫類變量/全局變量。靜態變量 是隨着類的加載而加載到方法區中的靜態區,並且在靜態區中賦予了初始值。靜態變量是在對 象之前產生,所以可以不通過對象來調用,而是通過類來調用,所以可以通過類名.靜態變量的 方式調用靜態變量。由於每個對象在堆內存中存儲的是靜態變量在靜態區中的地址,所以所有 的對象本質上共用一個靜態變量。 Static 修飾成員方法:用static 修飾的方法就稱之為靜態方法,也叫類方法。靜態方法在類加載 的時候加載到了方法區中的靜態區,在調用的時候到棧內存中執行。---靜態方法是先於對象而 存在的。靜態方法可以通過類名.方法名的方式來調用執行。 靜態代碼塊:靜態代碼塊在類中是獨立於成員變量和成員方法的代碼塊。它不在任何一個方法 體內,jvm 在加載類時會執行靜態代碼塊,靜態代碼塊是先於構造代碼塊執行。靜態代碼塊在 類加載的時候執行,只執行一次。 靜態內部類:靜態內部類是指被聲明為靜態內部類,它可以不依賴與外部類實例對象而被實例 化,而通常的內部類需要在外部類實例化后才能實例化。靜態內部類不能與外部類有相同的名 字,不能訪問外部類的普通成員變量,只能訪問外部類中的靜態成員和靜態方法
1.56 Instanceof 有什么作用?
Instanceof 的作用是判斷一個引用類型的變量所指向的對象是否是一個類的實例。
1.57 什么是不可變類?
不可變類是指當創建了這個類的實例后,就不允許修改它的值了,也就是說,一個對象一旦被 創建出來,在其整個生命周期中,它的成員變量就不能被修改了。
1.58 值傳遞與引用傳遞的區別?
值傳遞:在方法調用中,實參會把它的值傳遞給形參,形參只是用實參的值初始化一個臨時的 存儲單元(方法內的局部變量),因此性參與實參雖然有着相同的值,但是卻有着不用的存儲單 元,因此對形參的改變不會影響實參的值。 引用傳遞:在方法的調用中,傳遞的是對象(也可以看做是對象的地址),這時形參與實參指向 同一塊存儲單元(對象),因此對形參的修改就會影響實參的值。
1.59 強制類型轉換的注意事項有哪些?
Java 在涉及 byte、short 和 char 類型的運算時,首先會把這些類型的變量值強制轉換為 int 類型, 然后對 int 類型的值進行計算,最后得到的值也是 int 類型。因此,如果把兩個 short 類型的值相 加,最后得到的結果是 int 型;如果把兩個 byte 類型的值相加,最后也會得到一個 int 類型的值。 如果需要得到 short 類型的結果,就必須顯示地把運算結果轉換為 short 類型。
1.60 ++i與 i++的區別?
++i 先運算后賦值,i++先賦值后運算。
1.61 字符串存儲的機制是什么?
字符串會存儲在常量池中。在給字符串賦值的時候,JVM 會檢查常量池中是否已經存在該字符 串,如果存在則直接引用該地址,否則會在常量池中創建該字符串然后引用該地址
ending...