1揣非、 Java語言有哪些特點
(1)簡單易學抡医、有豐富的類庫
(2)面向?qū)ο螅↗ava最重要的特性,讓程序耦合度更低早敬,內(nèi)聚性更高)
(3)與平臺無關(guān)性(JVM是Java跨平臺使用的根本)
(4)可靠安全
(5)支持多線程
2忌傻、面向?qū)ο蠛兔嫦蜻^程的區(qū)別
面向過程:是分析解決問題的步驟,然后用函數(shù)把這些步驟一步一步地實現(xiàn)搞监,然后在使用的時候一一調(diào)用則可水孩。性能較高,所以單片機琐驴、嵌入式開發(fā)等一般采用面向過程開發(fā)
面向?qū)ο螅菏前褬?gòu)成問題的事務(wù)分解成各個對象俘种,而建立對象的目的也不是為了完成一個個步驟秤标,而是為了描述某個事物在解決整個問題的過程中所發(fā)生的行為。面向?qū)ο笥蟹庋b宙刘、繼承苍姜、多態(tài)的特性,所以易維護悬包、易復(fù)用衙猪、易擴展〔冀可以設(shè)計出低耦合的系統(tǒng)垫释。但是性能上來說,比面向過程要低撑瞧。
3 饶号、八種基本數(shù)據(jù)類型的大小,以及他們的封裝類基本類型 大屑韭臁(字節(jié)) 默認值 封裝類
注:
1.int是基本數(shù)據(jù)類型茫船,Integer是int的封裝類,是引用類型扭屁。int默認值是0算谈,而Integer默認值是null,所以Integer能區(qū)分出0和null的情況料滥。一旦java看到null然眼,就知道這個引用還沒有指向某個對象,
2.基本數(shù)據(jù)類型在聲明時系統(tǒng)會自動給它分配空間葵腹,而引用類型聲明時只是分配了引用空間高每,必須通過實例化開辟數(shù)據(jù)空間之后才可以賦值。數(shù)組對象也是一個引用對象践宴,將一個數(shù)組賦值給另一個數(shù)組時只是復(fù)制了一個引用鲸匿,所以通過某一個數(shù)組所做的修改在另一個數(shù)組中也看的見。
雖然定義了boolean這種數(shù)據(jù)類型阻肩,但是只對它提供了非常有限的支持带欢。在Java虛擬機中沒有任何供boolean值專用的字節(jié)碼指令,Java語言表達式所操作的boolean值烤惊,在編譯之后都使用Java虛擬機中的int數(shù)據(jù)類型來代替乔煞,而boolean數(shù)組將會被編碼成Java虛擬機的byte數(shù)組,每個元素boolean元素占8位柒室。這樣我們可以得出boolean類型占了單獨使用是4個字節(jié)渡贾,在數(shù)組中又是1個字節(jié)。使用int的原因是雄右,對于當下32位的處理器(CPU)來說空骚,一次處理數(shù)據(jù)是32位(這里不是指的是32/64位系統(tǒng)锦溪,而是指CPU硬件層面),具有高效存取的特點府怯。
4、標識符的命名規(guī)則防楷。
標識符的含義:
是指在程序中牺丙,我們自己定義的內(nèi)容,譬如复局,類的名字冲簿,方法名稱以及變量名稱等等,都是標識符亿昏。
命名規(guī)則:(硬性要求)
標識符可以包含英文字母峦剔,0-9的數(shù)字,$以及_
標識符不能以數(shù)字開頭
標識符不是關(guān)鍵字
命名規(guī)范:(非硬性要求)
類名規(guī)范:首字符大寫角钩,后面每個單詞首字母大寫(大駝峰式)吝沫。
變量名規(guī)范:首字母小寫,后面每個單詞首字母大寫(小駝峰式)递礼。
方法名規(guī)范:同變量名惨险。
5、instanceof 關(guān)鍵字的作用
instanceof 嚴格來說是Java中的一個雙目運算符脊髓,用來測試一個對象是否為一個類的實例辫愉,用法為:
Boolean result = obj instanceof Class
其中 obj 為一個對象,Class 表示一個類或者一個接口将硝,當 obj 為 Class 的對象恭朗,或者是其直接或間接子類,或者是其接口的實現(xiàn)類依疼,結(jié)果result 都返回 true痰腮,否則返回false。
注意:編譯器會檢查 obj 是否能轉(zhuǎn)換成右邊的class類型律罢,如果不能轉(zhuǎn)換則直接報錯诽嘉,如果不能確定類型,則通過編譯弟翘,具體看運行時定虫腋。
int i = 0;
System.out.println(i instanceof Integer);//編譯不通過 i必須是引用類型,不能是基本類型
System.out.println(i instanceof Object);//編譯不通過
Integer integer = new Integer(1);
System.out.println(integer instanceof Integer);//true
//false ,在 JavaSE規(guī)范 中對 instanceof 運算符的規(guī)定就是:如果 obj 為 null稀余,那么將返回
false悦冀。
6、Java自動裝箱與拆箱
裝箱就是自動將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型(int-->Integer)睛琳;調(diào)用方法:Integer的valueOf(int) 方法
拆箱就是自動將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型(Integer-->int)盒蟆。調(diào)用方法:Integer的intValue方法
在Java SE5之前踏烙,如果要生成一個數(shù)值為10的Integer對象,必須這樣進行:
Integer i = new Integer(10);
而在從Java SE5開始就提供了自動裝箱的特性历等,如果要生成一個數(shù)值為10的Integer對象讨惩,只需要這
樣就可以了:
Integer i = 10;
7、 重載和重寫的區(qū)別
重寫(Override)
從字面上看寒屯,重寫就是 重新寫一遍的意思荐捻。其實就是在子類中把父類本身有的方法重新寫一遍。子類繼承了父類原有的方法寡夹,但有時子類并不想原封不動的繼承父類中的某個方法处面,所以在方法名,參數(shù)列表菩掏,返回類型(除過子類中方法的返回值是父類中方法返回值的子類時)都相同的情況下魂角, 對方法體進行修改或重寫,這就是重寫智绸。但要注意子類函數(shù)的訪問修飾權(quán)限不能少于父類的野揪。
public class Father {
public static void main(String[] args) {
// TODO Auto-generated method stub
Son s = new Son();
s.sayHello();
}
public void sayHello() {
System.out.println("Hello");
}
}
class Son extends Father{
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("hello by ");
}
}
重寫 總結(jié):
(1)發(fā)生在父類與子類之間
(2)方法名,參數(shù)列表瞧栗,返回類型(除過子類中方法的返回類型是父類中返回類型的子類)必須相同
(3)訪問修飾符的限制一定要大于被重寫方法的訪問修飾符(public>protected>default>private)
(4)重寫方法一定不能拋出新的檢查異炒烟簦或者比被重寫方法申明更加寬泛的檢查型異常
重載(Overload)
在一個類中,同名的方法如果有不同的參數(shù)列表(參數(shù)類型不同沼溜、參數(shù)個數(shù)不同甚至是參數(shù)順序不同)
則視為重載平挑。同時,重載對返回類型沒有要求系草,可以相同也可以不同通熄,但不能通過返回類型是否相同來
判斷重載。
public static void main(String[] args) {
// TODO Auto-generated method stub
Father s = new Father();
s.sayHello();
s.sayHello("wintershii");
}
public void sayHello() {
System.out.println("Hello");
}
public void sayHello(String name) {
System.out.println("Hello" + " " + name);
}
}
重載 總結(jié):
(1)重載Overload是一個類中多態(tài)性的一種表現(xiàn)
(2)重載要求同名方法的參數(shù)列表不同(參數(shù)類型找都,參數(shù)個數(shù)甚至是參數(shù)順序)
(3)重載的時候唇辨,返回值類型可以相同也可以不相同。無法以返回型別作為重載函數(shù)的區(qū)分標準
8能耻、 equals與==的區(qū)別
== :
== 比較的是變量(棧)內(nèi)存中存放的對象的(堆)內(nèi)存地址赏枚,用來判斷兩個對象的地址是否相同,即是否是指相同一個對象晓猛。比較的是真正意義上的指針操作饿幅。
(1)比較的是操作符兩端的操作數(shù)是否是同一個對象。
(2)兩邊的操作數(shù)必須是同一類型的(可以是父子類之間)才能編譯通過戒职。
(3)比較的是地址栗恩,如果是具體的阿拉伯數(shù)字的比較,值相等則為true洪燥,如:
int a=10 與 long b=10L 與 double c=10.0都是相同的(為true)磕秤,因為他們都指向地址為10的堆乳乌。
equals:
equals用來比較的是兩個對象的內(nèi)容是否相等,由于所有的類都是繼承自java.lang.Object類的市咆,所以適用于所有對象汉操,如果沒有對該方法進行覆蓋的話,調(diào)用的仍然是Object類中的方法蒙兰,而Object中的equals方法返回的卻是==的判斷磷瘤。
總結(jié):
所有比較是否相等時,都是用equals 并且在對常量相比較時癞己,把常量寫在前面,因為使用object的equals object可能為null 則空指針在阿里的代碼規(guī)范中只使用equals 梭伐,阿里插件默認會識別痹雅,并可以快速修改,推薦安裝阿里插件來排查老代碼使用“==”糊识,替換成equals
![
9绩社、 Hashcode的作用
java的集合有兩類,一類是List赂苗,還有一類是Set愉耙。前者有序可重復(fù),后者無序不重復(fù)拌滋。當我們在set中插入的時候怎么判斷是否已經(jīng)存在該元素呢朴沿,可以通過equals方法。但是如果元素太多败砂,用這樣的方法就會比較滿赌渣。
于是有人發(fā)明了哈希算法來提高集合中查找元素的效率。這種方式將集合分成若干個存儲區(qū)域昌犹,每個對象可以計算出一個哈希碼坚芜,可以將哈希碼分組,每組分別對應(yīng)某個存儲區(qū)域斜姥,根據(jù)一個對象的哈希碼就可以確定該對象應(yīng)該存儲的那個區(qū)域鸿竖。
hashCode方法可以這樣理解:它返回的就是根據(jù)對象的內(nèi)存地址換算出的一個值。這樣一來铸敏,當集合要添加新的元素時缚忧,先調(diào)用這個元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上杈笔。如果這個位置上沒有元素搔谴,它就可以直接存儲在這個位置上,不用再進行任何比較了桩撮;如果這個位置上已經(jīng)有元素了敦第,就調(diào)用它的equals方法與新元素進行比較峰弹,相同的話就不存了,不相同就散列其它的地址芜果。這樣一來實際調(diào)用equals方法的次數(shù)就大大降低了鞠呈,幾乎只需要一兩次。
10右钾、String蚁吝、String StringBu?er 和 StringBuilder 的區(qū)別是什么?
String是只讀字符串,它并不是基本數(shù)據(jù)類型舀射,而是一個對象窘茁。從底層源碼來看是一個?nal類型的字符數(shù)組,所引用的字符串不能被改變脆烟,一經(jīng)定義山林,無法再增刪改。每次對String的操作都會生成新的String對象邢羔。
private final char value[];
每次+操作 :隱式在堆上new了一個跟原字符串相同的StringBuilder對象驼抹,再調(diào)用append方法 拼接+后面的字符。
StringBu?er和StringBuilder他們兩都繼承了AbstractStringBuilder抽象類拜鹤,從AbstractStringBuilder抽象類中我們可以看到
/**
* The value is used for character storage.
*/
char[] value;
他們的底層都是可變的字符數(shù)組框冀,所以在進行頻繁的字符串操作時,建議使用StringBu?er和StringBuilder來進行操作敏簿。另外StringBu?er 對方法加了同步鎖或者對調(diào)用的方法加了同步鎖明也,所以是線程安全的。StringBuilder 并沒有對方法進行加同步鎖惯裕,所以是非線程安全的诡右。
11、ArrayList和linkedList的區(qū)別
Array(數(shù)組)是基于索引(index)的數(shù)據(jù)結(jié)構(gòu)轻猖,它使用索引在數(shù)組中搜索和讀取數(shù)據(jù)是很快的帆吻。
Array獲取數(shù)據(jù)的時間復(fù)雜度是O(1),但是要刪除數(shù)據(jù)卻是開銷很大,因為這需要重排數(shù)組中的所有數(shù)據(jù),(因為刪除數(shù)據(jù)以后, 需要把后面所有的數(shù)據(jù)前移)
缺點: 數(shù)組初始化必須指定初始化的長度, 否則報錯
例如:
int[] a = new int[4];
//推介使用int[] 這種方式初始化
int c[] = {23,43,56,78};
//長度:4咙边,索引范圍:[0,3]
List—是一個有序的集合猜煮,可以包含重復(fù)的元素,提供了按索引訪問的方式败许,它繼承Collection王带。
List有兩個重要的實現(xiàn)類:ArrayList和LinkedList
ArrayList: 可以看作是能夠自動增長容量的數(shù)組
ArrayList的toArray方法返回一個數(shù)組
ArrayList的asList方法返回一個列表
ArrayList底層的實現(xiàn)是Array, 數(shù)組擴容實現(xiàn)
LinkList是一個雙鏈表,在添加和刪除元素時具有比ArrayList更好的性能.但在get與set方面弱于
ArrayList.當然,這些對比都是指數(shù)據(jù)量很大或者操作很頻繁。
12市殷、 HashMap和HashTable的區(qū)別
(1)兩者父類不同
HashMap是繼承自AbstractMap類愕撰,而Hashtable是繼承自Dictionary類。不過它們都實現(xiàn)了同時實現(xiàn)了map、Cloneable(可復(fù)制)搞挣、Serializable(可序列化)這三個接口带迟。
(2)對外提供的接口不同
Hashtable比HashMap多提供了elments() 和contains() 兩個方法。
elments() 方法繼承自Hashtable的父類Dictionnary囱桨。elements() 方法用于返回此Hashtable中的value的枚舉仓犬。
contains()方法判斷該Hashtable是否包含傳入的value。它的作用與containsValue()一致舍肠。事實上搀继,contansValue() 就只是調(diào)用了一下contains() 方法。
(3)對null的支持不同
Hashtable:key和value都不能為null翠语。
HashMap:key可以為null叽躯,但是這樣的key只能有一個,因為必須保證key的唯一性肌括;可以有多個key值對應(yīng)的value為null点骑。
(4)安全性不同
HashMap是線程不安全的,在多線程并發(fā)的環(huán)境下们童,可能會產(chǎn)生死鎖等問題畔况,因此需要開發(fā)人員自己處理多線程的安全問題鲸鹦。
Hashtable是線程安全的慧库,它的每個方法上都有synchronized 關(guān)鍵字,因此可直接用于多線程中馋嗜。雖然HashMap是線程不安全的齐板,但是它的效率遠遠高于Hashtable,這樣設(shè)計是合理的葛菇,因為大部分的使用場景都是單線程甘磨。當需要多線程操作的時候可以使用線程安全的ConcurrentHashMap。
ConcurrentHashMap雖然也是線程安全的眯停,但是它的效率比Hashtable要高好多倍济舆。因為
ConcurrentHashMap使用了分段鎖,并不對整個數(shù)據(jù)進行鎖定莺债。
(5)計算hash值的方法不同
13滋觉、 Collection包結(jié)構(gòu),與Collections的區(qū)別
Collection是集合類的上級接口齐邦,子接口有 Set椎侠、List、LinkedList措拇、ArrayList我纪、Vector、Stack、Set浅悉;Collections是集合類的一個幫助類趟据, 它包含有各種有關(guān)集合操作的靜態(tài)多態(tài)方法,用于實現(xiàn)對各種集合的搜索仇冯、排序之宿、線程安全化等操作。此類不能實例化苛坚,就像一個工具類比被,服務(wù)于Java的Collection框架。
14泼舱、 Java的四種引用等缀,強弱軟虛
強引用
強引用是平常中使用最多的引用,強引用在程序內(nèi)存不足(OOM)的時候也不會被回收娇昙,使用方式:
String str = new String("str");
軟引用
軟引用在程序內(nèi)存不足時尺迂,會被回收,使用方式:
// 注意:wrf這個引用也是強引用冒掌,它是指向SoftReference這個對象的噪裕,
// 這里的軟引用指的是指向new String("str")的引用,也就是SoftReference類中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));
可用場景:創(chuàng)建緩存的時候股毫,創(chuàng)建的對象放進緩存中膳音,當內(nèi)存不足時,JVM就會回收早先創(chuàng)建的對象铃诬。
弱引用
弱引用就是只要JVM垃圾回收器發(fā)現(xiàn)了它祭陷,就會將之回收,使用方式:
WeakReference<String> wrf = new WeakReference<String>(str);
可用場景:Java源碼中的 java.util.WeakHashMap中的 key就是使用弱引用趣席,我的理解就是兵志,一旦我不需要某個引用,JVM會自動幫我處理它宣肚,這樣我就不需要做其它操作想罕。
虛引用
虛引用的回收機制跟弱引用差不多,但是它被回收之前霉涨,會被放入 ReferenceQueue中按价。注意哦,其它引用是被JVM回收后才被傳入 ReferenceQueue中的嵌纲。由于這個機制俘枫,所以虛引用大多被用于引用銷毀前的處理工作。還有就是逮走,虛引用創(chuàng)建的時候鸠蚪,必須帶有 ReferenceQueue,使用
例子:
PhantomReference<String> prf = new PhantomReference<String>(new
String("str"), new ReferenceQueue<>());
可用場景:對象銷毀前的一些操作汤纸,比如說資源釋放等愉棱。** Object.finalize()雖然也可以做這類動作,但是這個方式即不安全又低效
15稽煤、 泛型常用特點 (待補充)
泛型是Java SE 1.5之后的特性蘸鲸, 《Java 核心技術(shù)》中對泛型的定義是:
“泛型” 意味著編寫的代碼可以被不同類型的對象所重用妖谴。
“泛型”,顧名思義酌摇,“泛指的類型”膝舅。我們提供了泛指的概念,但具體執(zhí)行的時候卻可以有具體的規(guī)則來約束窑多,比如我們用的非常多的ArrayList就是個泛型類仍稀,ArrayList作為集合可以存放各種元素,如Integer, String埂息,自定義的各種類型等技潘,但在我們使用的時候通過具體的規(guī)則來約束,如我們可以約束集合中只存放Integer類型的元素千康,如
List<Integer> iniData = new ArrayList<>()
使用泛型的好處享幽?
以集合來舉例,使用泛型的好處是我們不必因為添加元素類型的不同而定義不同類型的集合拾弃,如整型集合類值桩,浮點型集合類,字符串集合類砸彬,我們可以定義一個集合來存放整型颠毙、浮點型斯入,字符串型數(shù)據(jù)砂碉,而這并不是最重要的,因為我們只要把底層存儲設(shè)置了Object即可刻两,添加的數(shù)據(jù)全部都可向上轉(zhuǎn)型為Object增蹭。更重要的是我們可以通過規(guī)則按照自己的想法控制存儲的數(shù)據(jù)類型。
16磅摹、Java創(chuàng)建對象有幾種方式滋迈?
java中提供了以下四種創(chuàng)建對象的方式:
(1)new創(chuàng)建新對象
(2)通過反射機制
(3)采用clone機制
(4)通過序列化機制
17、有沒有可能兩個不相等的對象有相同的hashcode
有可能.在產(chǎn)生hash沖突時,兩個不相等的對象就會有相同的 hashcode 值.當hash沖突產(chǎn)生時,一般有以下幾種方式來處理:
(1)拉鏈法:每個哈希表節(jié)點都有一個next指針,多個哈希表節(jié)點可以用next指針構(gòu)成一個單向鏈表户誓,被分配到同一個索引上的多個節(jié)點可以用這個單向鏈表進行存儲.
(2)開放定址法:一旦發(fā)生了沖突,就去尋找下一個空的散列地址,只要散列表足夠大,空的散列地址總能找到,并將記錄存入
(3)再哈希:又叫雙哈希法,有多個不同的Hash函數(shù).當發(fā)生沖突時,使用第二個,第三個….等哈希函數(shù)計算地址,直到無沖突.
18饼灿、深拷貝和淺拷貝的區(qū)別是什么?
淺拷貝:被復(fù)制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象.換言之,淺拷貝僅僅復(fù)制所考慮的對象,而不復(fù)制它所引用的對象.
深拷貝:被復(fù)制對象的所有變量都含有與原來的對象相同的值.而那些引用其他對象的變量將指向被復(fù)制過的新對象.而不再是原有的那些被引用的對象.換言之.深拷貝把要復(fù)制的對象所引用的對象都
19、?nal有哪些用法?
?nal也是很多面試喜歡問的地方,但我覺得這個問題很無聊,通常能回答下以下5點就不錯了:
(1)被?nal修飾的類不可以被繼承
(2)被?nal修飾的方法不可以被重寫
(3)被?nal修飾的變量不可以被改變.如果修飾引用,那么表示引用不可變,引用指向的內(nèi)容可變.
(4)被?nal修飾的方法,JVM會嘗試將其內(nèi)聯(lián),以提高運行效率
(5)被?nal修飾的常量,在編譯階段會存入常量池中.
除此之外,編譯器對?nal域要遵守的兩個重排序規(guī)則更好:
在構(gòu)造函數(shù)內(nèi)對一個?nal域的寫入,與隨后把這個被構(gòu)造對象的引用賦值給一個引用變量,這兩個操作之間不能重排序
初次讀一個包含?nal域的對象的引用,與隨后初次讀這個?nal域,這兩個操作之間不能重排序.
20帝美、static都有哪些用法?
所有的人都知道static關(guān)鍵字這兩個基本的用法:靜態(tài)變量和靜態(tài)方法.也就是被static所修飾的變量/方法都屬于類的靜態(tài)資源,類實例所共享.
除了靜態(tài)變量和靜態(tài)方法之外,static也用于靜態(tài)塊,多用于初始化操作:
public calss PreCache{
static{
//執(zhí)行相關(guān)操作
}
}
此外static也多用于修飾內(nèi)部類,此時稱之為靜態(tài)內(nèi)部類.
最后一種用法就是靜態(tài)導(dǎo)包,即 import static.import static是在JDK 1.5之后引入的新特性,可以用來指定導(dǎo)入某個類中的靜態(tài)資源,并且不需要使用類名,可以直接使用資源名,比如:
import static java.lang.Math.*;
public class Test{
public static void main(String[] args){
//System.out.println(Math.sin(20));傳統(tǒng)做法
System.out.println(sin(20));
}
}
21碍彭、3*0.1 0.3返回值是什么
false,因為有些浮點數(shù)不能完全精確的表示出來.
22、a=a+b與a+=b有什么區(qū)別嗎?
操作符會進行隱式自動類型轉(zhuǎn)換,此處a+=b隱式的將加操作的結(jié)果類型強制轉(zhuǎn)換為持有結(jié)果的類型,
byte a = 127;
byte b = 127;
b = a + b;
// 報編譯錯誤:cannot convert from int to byte
b += a;
以下代碼是否有錯,有的話怎么改?
short s1= 1;
s1 = s1 + 1;
有錯誤.short類型在進行運算時會自動提升為int類型,也就是說 s1+1的運算結(jié)果是int類型,而s1是short類型,此時編譯器會報錯.
正確寫法:
short s1= 1;
s1 += 1;
+=操作符會對右邊的表達式結(jié)果強轉(zhuǎn)匹配左邊的數(shù)據(jù)類型,所以沒錯.
23庇忌、try catch ?nally舞箍,try里有return,?nally還執(zhí)行么皆疹?
執(zhí)行疏橄,并且?nally的執(zhí)行早于try里面的return
結(jié)論:
(1)不管有木有出現(xiàn)異常,?nally塊中代碼都會執(zhí)行略就;
(2)當try和catch中有return時捎迫,?nally仍然會執(zhí)行;
(3)?nally是在return后面的表達式運算后執(zhí)行的(此時并沒有返回運算后的值表牢,而是先把要返回的值保存起來立砸,管?nally中的代碼怎么樣,返回的值都不會改變初茶,任然是之前保存的值)颗祝,所以函數(shù)返回值是在?nally執(zhí)行前確定的;
(4)?nally中最好不要包含return恼布,否則程序會提前退出螺戳,返回值不是try或catch中保存的返回值。
24折汞、 Excption與Error包結(jié)構(gòu)
Java可拋出(Throwable)的結(jié)構(gòu)分為三種類型:被檢查的異常(CheckedException)倔幼,運行時異常(RuntimeException),錯誤(Error)爽待。
運行時異常
定義:RuntimeException及其子類都被稱為運行時異常损同。
特點:Java編譯器不會檢查它。也就是說鸟款,當程序中可能出現(xiàn)這類異常時膏燃,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它"何什,還是會編譯通過组哩。例如,除數(shù)為零時產(chǎn)生的
ArithmeticException異常处渣,數(shù)組越界時產(chǎn)生的IndexOutOfBoundsException異常伶贰,fail-fast機制產(chǎn)生的ConcurrentModi?cationException異常(java.util包下面的所有的集合類都是快速失敗的,“快速失敗”也就是fail-fast罐栈,它是Java集合的一種錯誤檢測機制黍衙。當多個線程對集合進行結(jié)構(gòu)上的改變的操作時,有可能會產(chǎn)生fail-fast機制荠诬。記住是有可能琅翻,而不是一定涯捻。例如:假設(shè)存在兩個線程(線程1、線程2)望迎,線程1通過Iterator在遍歷集合A中的元素障癌,在某個時候線程2修改了集合A的結(jié)構(gòu)(是結(jié)構(gòu)上面的
ConcurrentModi?cationException 異常,從而產(chǎn)生fail-fast機制辩尊,這個錯叫并發(fā)修改異常涛浙。Fail-safe,java.util.concurrent包下面的所有的類都是安全失敗的摄欲,在遍歷過程中轿亮,如果已經(jīng)遍歷的數(shù)組上的內(nèi)容變化了,迭代器不會拋出ConcurrentModi?cationException異常胸墙。如果未遍歷的數(shù)組上的內(nèi)容發(fā)生了變化我注,則有可能反映到迭代過程中。這就是ConcurrentHashMap迭代器弱一致的表現(xiàn)迟隅。ConcurrentHashMap的弱一致性主要是為了提升效率但骨,是一致性與效率之間的一種權(quán)衡。要成為強一致性智袭,就得到處使用鎖奔缠,甚至是全局鎖,這就與Hashtable和同步的HashMap一樣了吼野。)等校哎,都屬于運行時異常。
常見的五種運行時異常:
(1)ClassCastException(類轉(zhuǎn)換異常)
(2)IndexOutOfBoundsException(數(shù)組越界)
(3)NullPointerException(空指針異常)
(4)ArrayStoreException(數(shù)據(jù)存儲異常瞳步,操作數(shù)組是類型不一致)
(5)Bu?erOver?owException
被檢查異常
定義:Exception類本身闷哆,以及Exception的子類中除了"運行時異常"之外的其它子類都屬于被檢查異常。
特點 : Java編譯器會檢查它单起。此類異常抱怔,要么通過throws進行聲明拋出,要么通過try-catch進行捕獲處理馏臭,否則不能通過編譯野蝇。例如讼稚,CloneNotSupportedException就屬于被檢查異常括儒。當通過clone()接口去克隆一個對象,而該對象對應(yīng)的類沒有實現(xiàn)Cloneable接口锐想,就會拋出CloneNotSupportedException異常帮寻。被檢查異常通常都是可以恢復(fù)的。
如:
IOException
FileNotFoundException
SQLException
被檢查的異常適用于那些不是因程序引起的錯誤情況赠摇,比如:讀取文件時文件不存在引發(fā)的
FileNotFoundException 固逗。然而浅蚪,不被檢查的異常通常都是由于糟糕的編程引起的,比如:在對象引
用時沒有確保對象非空而引起的 NullPointerException 烫罩。
錯誤
定義 : Error類及其子類惜傲。
特點 : 和運行時異常一樣,編譯器也不會對錯誤進行檢查贝攒。
當資源不足盗誊、約束失敗、或是其它程序無法繼續(xù)運行的條件發(fā)生時隘弊,就產(chǎn)生錯誤哈踱。程序本身無法修復(fù)這些錯誤的。例如梨熙,VirtualMachineError就屬于錯誤开镣。出現(xiàn)這種錯誤會導(dǎo)致程序終止運行。OutOfMemoryError咽扇、ThreadDeath邪财。
Java虛擬機規(guī)范規(guī)定JVM的內(nèi)存分為了好幾塊,比如堆质欲,棧卧蜓,程序計數(shù)器,方法區(qū)等
25把敞、OOM你遇到過哪些情況弥奸,SOF你遇到過哪些情況
OOM:
(1)OutOfMemoryError異常
Java Heap 溢出:
一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess。
java堆用于存儲對象實例奋早,我們只要不斷的創(chuàng)建對象盛霎,并且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數(shù)量達到最大堆容量限制后產(chǎn)生內(nèi)存溢出異常耽装。
出現(xiàn)這種異常愤炸,一般手段是先通過內(nèi)存映像分析工具(如Eclipse Memory Analyzer)對dump出來的堆轉(zhuǎn)存快照進行分析,重點是確認內(nèi)存中的對象是否是必要的掉奄,先分清是因為內(nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Over?ow)规个。
如果是內(nèi)存泄漏,可進一步通過工具查看泄漏對象到GCRoots的引用鏈姓建。于是就能找到泄漏對象是通過怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無法自動回收诞仓。
如果不存在泄漏,那就應(yīng)該檢查虛擬機的參數(shù)(-Xmx與-Xms)的設(shè)置是否適當速兔。
(2)虛擬機棧和本地方法棧溢出
如果線程請求的棧深度大于虛擬機所允許的最大深度墅拭,將拋出StackOver?owError異常。
如果虛擬機在擴展棧時無法申請到足夠的內(nèi)存空間涣狗,則拋出OutOfMemoryError異常
這里需要注意當棧的大小越大可分配的線程數(shù)就越少谍婉。
(3)運行時常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGenspace
如果要向運行時常量池中添加內(nèi)容舒憾,最簡單的做法就是使用String.intern()這個Native方法。該方法的作用是:如果池中已經(jīng)包含一個等于此String的字符串穗熬,則返回代表池中這個字符串的String對象镀迂;否則,將此String對象包含的字符串添加到常量池中唤蔗,并且返回此String對象的引用招拙。由于常量池分配在方法區(qū)內(nèi),我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區(qū)的大小措译,從而間接限制其中常量池的容量别凤。
(4)方法區(qū)溢出
方法區(qū)用于存放Class的相關(guān)信息,如類名领虹、訪問修飾符规哪、常量池、字段描述塌衰、方法描述等诉稍。也有可能是方法區(qū)中保存的class對象沒有被及時回收掉或者class信息占用的內(nèi)存超過了我們配置。
異常信息:java.lang.OutOfMemoryError:PermGenspace
方法區(qū)溢出也是一種常見的內(nèi)存溢出異常最疆,一個類如果要被垃圾收集器回收杯巨,判定條件是很苛刻的。在經(jīng)常動態(tài)生成大量Class的應(yīng)用中努酸,要特別注意這點服爷。
SOF(堆棧溢出StackOver?ow):
StackOver?owError 的定義:當應(yīng)用程序遞歸太深而發(fā)生堆棧溢出時,拋出該錯誤获诈。
因為棧一般默認為1-2m仍源,一旦出現(xiàn)死循環(huán)或者是大量的遞歸調(diào)用,在不斷的壓棧過程中舔涎,造成棧容量超過1m而導(dǎo)致溢出笼踩。
棧溢出的原因:遞歸調(diào)用,大量循環(huán)或死循環(huán)亡嫌,全局變量是否過多嚎于,數(shù)組、List挟冠、map數(shù)據(jù)過大于购。
26、 簡述線程圃郊、程序价涝、進程的基本概念。以及他們之間關(guān)系是什么?
線程與進程相似持舆,但線程是一個比進程更小的執(zhí)行單位色瘩。一個進程在其執(zhí)行的過程中可以產(chǎn)生多個線程。與進程不同的是同類的多個線程共享同一塊內(nèi)存空間和一組系統(tǒng)資源逸寓,所以系統(tǒng)在產(chǎn)生一個線程居兆,或是在各個線程之間作切換工作時,負擔要比進程小得多竹伸,也正因為如此泥栖,線程也被稱為輕量級進程。程序是含有指令和數(shù)據(jù)的文件勋篓,被存儲在磁盤或其他的數(shù)據(jù)存儲設(shè)備中吧享,也就是說程序是靜態(tài)的代碼。
進程是程序的一次執(zhí)行過程譬嚣,是系統(tǒng)運行程序的基本單位钢颂,因此進程是動態(tài)的。系統(tǒng)運行一個程序即是一個進程從創(chuàng)建拜银,運行到消亡的過程殊鞭。簡單來說,一個進程就是一個執(zhí)行中的程序尼桶,它在計算機中一個指令接著一個指令地執(zhí)行著操灿,同時,每個進程還占有某些系統(tǒng)資源如 CPU 時間泵督,內(nèi)存空間趾盐,文件,輸入輸出設(shè)備的使用權(quán)等等小腊。換句話說谤碳,當程序在執(zhí)行時,將會被操作系統(tǒng)載入內(nèi)存中溢豆。線程是進程劃分成的更小的運行單位蜒简。線程和進程最大的不同在于基本上各進程是獨立的,而各線程則不一定漩仙,因為同一進程中的線程極有可能會相互影響搓茬。從另一角度來說,進程屬于操作系統(tǒng)的范疇队他,主要是同一段時間內(nèi)卷仑,可以同時執(zhí)行一個以上的程序,而線程則是在同一程序內(nèi)幾乎同時執(zhí)行一個以上的程序段麸折。
27锡凝、線程有哪些基本狀態(tài)?(補充)
Java 線程在運行的生命周期中的指定時刻只可能處于下面 6 種不同狀態(tài)的其中一個狀態(tài)(圖源《Java并發(fā)編程藝術(shù)》4.1.4 節(jié))。
28垢啼、Java 序列化中如果有些字段不想進行序列化窜锯,怎么辦张肾?
對于不想進行序列化的變量,使用 transient 關(guān)鍵字修飾锚扎。
transient 關(guān)鍵字的作用是:阻止實例中那些用此關(guān)鍵字修飾的的變量序列化吞瞪;當對象被反序列化時,被 transient 修飾的變量值不會被持久化和恢復(fù)驾孔。transient 只能修飾變量芍秆,不能修飾類和方法。
29翠勉、Java 中 IO 流
Java 中 IO 流分為幾種?
(1)按照流的流向分妖啥,可以分為輸入流和輸出流;
(2)按照操作單元劃分对碌,可以劃分為字節(jié)流和字符流荆虱;
(3)按照流的角色劃分為節(jié)點流和處理流。
Java Io 流共涉及 40 多個類俭缓,這些類看上去很雜亂克伊,但實際上很有規(guī)則,而且彼此之間存在非常緊密的聯(lián)系华坦, Java I0 流的 40 多個類都是從如下 4 個抽象類基類中派生出來的愿吹。
InputStream/Reader: 所有的輸入流的基類,前者是字節(jié)輸入流惜姐,后者是字符輸入流犁跪。
OutputStream/Writer: 所有輸出流的基類,前者是字節(jié)輸出流歹袁,后者是字符輸出流坷衍。
按操作方式分類結(jié)構(gòu)圖:
按操作對象分類結(jié)構(gòu)圖:
30、 Java IO與 NIO的區(qū)別(補充)
NIO即New IO条舔,這個庫是在JDK1.4中才引入的枫耳。NIO和IO有相同的作用和目的,但實現(xiàn)方式不同孟抗,NIO主要用到的是塊迁杨,所以NIO的效率要比IO高很多。在Java API中提供了兩套NIO凄硼,一套是針對標準輸入輸出NIO铅协,另一套就是網(wǎng)絡(luò)編程NIO。
31摊沉、java反射的作用于原理
(1)定義:
反射機制是在運行時狐史,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意個對象骏全,都能夠調(diào)用它的任意一個方法苍柏。在java中,只要給定類的名字吟温,就可以通過反射機制來獲得類的所有信息序仙。
這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為Java語言的反射機制突颊。
(2)哪里會用到反射機制鲁豪?
jdbc就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');
//加載MySQL的驅(qū)動類
這就是反射。如hibernate律秃,struts等框架使用反射實現(xiàn)的爬橡。
第一步:獲取Class對象,有4中方法:
1)Class.forName(“類的路徑”)棒动;
2)類名.class
3)對象名.getClass()
4)基本類型的包裝類糙申,可以調(diào)用包裝類的Type屬性來獲得該包裝類的Class對象
(3)實現(xiàn)Java反射的類:
1)Class:表示正在運行的Java應(yīng)用程序中的類和接口
注意:所有獲取對象的信息都需要Class類來實現(xiàn)。
2)Field:提供有關(guān)類和接口的屬性信息船惨,以及對它的動態(tài)訪問權(quán)限柜裸。
3)Constructor:提供關(guān)于類的單個構(gòu)造方法的信息以及它的訪問權(quán)限
4)Method:提供類或接口中某個方法的信息
(4)反射機制的優(yōu)缺點:
優(yōu)點:
1)能夠運行時動態(tài)獲取類的實例,提高靈活性粱锐;
2)與動態(tài)編譯結(jié)合
缺點:
1)使用反射性能較低疙挺,需要解析字節(jié)碼,將內(nèi)存中的對象進行解析怜浅。
解決方案:
1铐然、通過setAccessible(true)關(guān)閉JDK的安全檢查來提升反射速度;
2恶座、多次創(chuàng)建一個類的實例時搀暑,有緩存會快很多
3、Re?ectASM工具類跨琳,通過字節(jié)碼生成的方式加快反射速度
2)相對不安全自点,破壞了封裝性(因為通過反射可以獲得私有方法和屬性)
32、說說List,Set,Map三者的區(qū)別脉让?
List(對付順序的好幫手):List接口存儲一組不唯一(可以有多個元素引用相同的對象)桂敛,有序的對象
Set(注重獨一無二的性質(zhì)): 不允許重復(fù)的集合。不會有多個元素引用相同的對象侠鳄。
Map(用Key來搜索的專家): 使用鍵值對存儲埠啃。Map會維護與Key有關(guān)聯(lián)的值。兩個Key可以引用相同的對象伟恶,但Key不能重復(fù)碴开,典型的Key是String類型,但也可以是任何對象。