1、 Java語言有哪些特點(diǎn)
(1)簡單易學(xué)设塔、有豐富的類庫
(2)面向?qū)ο螅↗ava最重要的特性凄吏,讓程序耦合度更低,內(nèi)聚性更高)
(3)與平臺(tái)無關(guān)性(JVM是Java跨平臺(tái)使用的根本)
(4)可靠安全
(5)支持多線程
2闰蛔、面向?qū)ο蠛兔嫦蜻^程的區(qū)別
面向過程:是分析解決問題的步驟痕钢,然后用函數(shù)把這些步驟一步一步地實(shí)現(xiàn),然后在使用的時(shí)候一一調(diào)用則可钞护。性能較高盖喷,所以單片機(jī)、嵌入式開發(fā)等一般采用面向過程開發(fā)
面向?qū)ο螅菏前褬?gòu)成問題的事務(wù)分解成各個(gè)對(duì)象难咕,而建立對(duì)象的目的也不是為了完成一個(gè)個(gè)步驟课梳,而是為了描述某個(gè)事物在解決整個(gè)問題的過程中所發(fā)生的行為距辆。面向?qū)ο笥蟹庋b、繼承暮刃、多態(tài)的特性跨算,所以易維護(hù)、易復(fù)用椭懊、易擴(kuò)展诸蚕。可以設(shè)計(jì)出低耦合的系統(tǒng)氧猬。但是性能上來說背犯,比面向過程要低。
3 盅抚、八種基本數(shù)據(jù)類型的大小漠魏,以及他們的封裝類基本類型 大小(字節(jié)) 默認(rèn)值 封裝類
注:
1.int是基本數(shù)據(jù)類型妄均,Integer是int的封裝類柱锹,是引用類型。int默認(rèn)值是0丰包,而Integer默認(rèn)值是null禁熏,所以Integer能區(qū)分出0和null的情況。一旦java看到null邑彪,就知道這個(gè)引用還沒有指向某個(gè)對(duì)象瞧毙,
2.基本數(shù)據(jù)類型在聲明時(shí)系統(tǒng)會(huì)自動(dòng)給它分配空間,而引用類型聲明時(shí)只是分配了引用空間锌蓄,必須通過實(shí)例化開辟數(shù)據(jù)空間之后才可以賦值升筏。數(shù)組對(duì)象也是一個(gè)引用對(duì)象,將一個(gè)數(shù)組賦值給另一個(gè)數(shù)組時(shí)只是復(fù)制了一個(gè)引用瘸爽,所以通過某一個(gè)數(shù)組所做的修改在另一個(gè)數(shù)組中也看的見您访。
雖然定義了boolean這種數(shù)據(jù)類型,但是只對(duì)它提供了非常有限的支持剪决。在Java虛擬機(jī)中沒有任何供boolean值專用的字節(jié)碼指令灵汪,Java語言表達(dá)式所操作的boolean值,在編譯之后都使用Java虛擬機(jī)中的int數(shù)據(jù)類型來代替柑潦,而boolean數(shù)組將會(huì)被編碼成Java虛擬機(jī)的byte數(shù)組享言,每個(gè)元素boolean元素占8位。這樣我們可以得出boolean類型占了單獨(dú)使用是4個(gè)字節(jié)渗鬼,在數(shù)組中又是1個(gè)字節(jié)览露。使用int的原因是,對(duì)于當(dāng)下32位的處理器(CPU)來說譬胎,一次處理數(shù)據(jù)是32位(這里不是指的是32/64位系統(tǒng)差牛,而是指CPU硬件層面)命锄,具有高效存取的特點(diǎn)。
4偏化、標(biāo)識(shí)符的命名規(guī)則脐恩。
標(biāo)識(shí)符的含義:
是指在程序中,我們自己定義的內(nèi)容侦讨,譬如驶冒,類的名字,方法名稱以及變量名稱等等韵卤,都是標(biāo)識(shí)符骗污。
命名規(guī)則:(硬性要求)
標(biāo)識(shí)符可以包含英文字母,0-9的數(shù)字怜俐,$以及_
標(biāo)識(shí)符不能以數(shù)字開頭
標(biāo)識(shí)符不是關(guān)鍵字
命名規(guī)范:(非硬性要求)
類名規(guī)范:首字符大寫身堡,后面每個(gè)單詞首字母大寫(大駝峰式)。
變量名規(guī)范:首字母小寫拍鲤,后面每個(gè)單詞首字母大寫(小駝峰式)。
方法名規(guī)范:同變量名汞扎。
5季稳、instanceof 關(guān)鍵字的作用
instanceof 嚴(yán)格來說是Java中的一個(gè)雙目運(yùn)算符,用來測試一個(gè)對(duì)象是否為一個(gè)類的實(shí)例澈魄,用法為:
Boolean result = obj instanceof Class
其中 obj 為一個(gè)對(duì)象景鼠,Class 表示一個(gè)類或者一個(gè)接口,當(dāng) obj 為 Class 的對(duì)象痹扇,或者是其直接或間接子類铛漓,或者是其接口的實(shí)現(xiàn)類,結(jié)果result 都返回 true鲫构,否則返回false浓恶。
注意:編譯器會(huì)檢查 obj 是否能轉(zhuǎn)換成右邊的class類型,如果不能轉(zhuǎn)換則直接報(bào)錯(cuò)结笨,如果不能確定類型包晰,則通過編譯,具體看運(yùn)行時(shí)定炕吸。
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ī)范 中對(duì) instanceof 運(yùn)算符的規(guī)定就是:如果 obj 為 null,那么將返回
false赫模。
6树肃、Java自動(dòng)裝箱與拆箱
裝箱就是自動(dòng)將基本數(shù)據(jù)類型轉(zhuǎn)換為包裝器類型(int-->Integer);調(diào)用方法:Integer的valueOf(int) 方法
拆箱就是自動(dòng)將包裝器類型轉(zhuǎn)換為基本數(shù)據(jù)類型(Integer-->int)瀑罗。調(diào)用方法:Integer的intValue方法
在Java SE5之前胸嘴,如果要生成一個(gè)數(shù)值為10的Integer對(duì)象莉钙,必須這樣進(jìn)行:
Integer i = new Integer(10);
而在從Java SE5開始就提供了自動(dòng)裝箱的特性,如果要生成一個(gè)數(shù)值為10的Integer對(duì)象筛谚,只需要這
樣就可以了:
Integer i = 10;
7磁玉、 重載和重寫的區(qū)別
重寫(Override)
從字面上看,重寫就是 重新寫一遍的意思驾讲。其實(shí)就是在子類中把父類本身有的方法重新寫一遍蚊伞。子類繼承了父類原有的方法,但有時(shí)子類并不想原封不動(dòng)的繼承父類中的某個(gè)方法吮铭,所以在方法名时迫,參數(shù)列表,返回類型(除過子類中方法的返回值是父類中方法返回值的子類時(shí))都相同的情況下谓晌, 對(duì)方法體進(jìn)行修改或重寫掠拳,這就是重寫。但要注意子類函數(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)
在一個(gè)類中姐刁,同名的方法如果有不同的參數(shù)列表(參數(shù)類型不同、參數(shù)個(gè)數(shù)不同甚至是參數(shù)順序不同)
則視為重載烦味。同時(shí)聂使,重載對(duì)返回類型沒有要求,可以相同也可以不同谬俄,但不能通過返回類型是否相同來
判斷重載柏靶。
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是一個(gè)類中多態(tài)性的一種表現(xiàn)
(2)重載要求同名方法的參數(shù)列表不同(參數(shù)類型,參數(shù)個(gè)數(shù)甚至是參數(shù)順序)
(3)重載的時(shí)候溃论,返回值類型可以相同也可以不相同屎蜓。無法以返回型別作為重載函數(shù)的區(qū)分標(biāo)準(zhǔn)
8、 equals與==的區(qū)別
== :
== 比較的是變量(棧)內(nèi)存中存放的對(duì)象的(堆)內(nèi)存地址蔬芥,用來判斷兩個(gè)對(duì)象的地址是否相同梆靖,即是否是指相同一個(gè)對(duì)象。比較的是真正意義上的指針操作笔诵。
(1)比較的是操作符兩端的操作數(shù)是否是同一個(gè)對(duì)象返吻。
(2)兩邊的操作數(shù)必須是同一類型的(可以是父子類之間)才能編譯通過。
(3)比較的是地址乎婿,如果是具體的阿拉伯?dāng)?shù)字的比較测僵,值相等則為true,如:
int a=10 與 long b=10L 與 double c=10.0都是相同的(為true),因?yàn)樗麄兌贾赶虻刂窞?0的堆捍靠。
equals:
equals用來比較的是兩個(gè)對(duì)象的內(nèi)容是否相等沐旨,由于所有的類都是繼承自java.lang.Object類的,所以適用于所有對(duì)象榨婆,如果沒有對(duì)該方法進(jìn)行覆蓋的話磁携,調(diào)用的仍然是Object類中的方法,而Object中的equals方法返回的卻是==的判斷良风。
總結(jié):
所有比較是否相等時(shí)谊迄,都是用equals 并且在對(duì)常量相比較時(shí),把常量寫在前面烟央,因?yàn)槭褂胦bject的equals object可能為null 則空指針在阿里的代碼規(guī)范中只使用equals 统诺,阿里插件默認(rèn)會(huì)識(shí)別,并可以快速修改疑俭,推薦安裝阿里插件來排查老代碼使用“==”粮呢,替換成equals
![
9、 Hashcode的作用
java的集合有兩類钞艇,一類是List啄寡,還有一類是Set。前者有序可重復(fù)香璃,后者無序不重復(fù)这难。當(dāng)我們在set中插入的時(shí)候怎么判斷是否已經(jīng)存在該元素呢,可以通過equals方法葡秒。但是如果元素太多,用這樣的方法就會(huì)比較滿嵌溢。
于是有人發(fā)明了哈希算法來提高集合中查找元素的效率眯牧。這種方式將集合分成若干個(gè)存儲(chǔ)區(qū)域,每個(gè)對(duì)象可以計(jì)算出一個(gè)哈希碼赖草,可以將哈希碼分組学少,每組分別對(duì)應(yīng)某個(gè)存儲(chǔ)區(qū)域,根據(jù)一個(gè)對(duì)象的哈希碼就可以確定該對(duì)象應(yīng)該存儲(chǔ)的那個(gè)區(qū)域。
hashCode方法可以這樣理解:它返回的就是根據(jù)對(duì)象的內(nèi)存地址換算出的一個(gè)值。這樣一來飒责,當(dāng)集合要添加新的元素時(shí)琼懊,先調(diào)用這個(gè)元素的hashCode方法,就一下子能定位到它應(yīng)該放置的物理位置上嗅定。如果這個(gè)位置上沒有元素,它就可以直接存儲(chǔ)在這個(gè)位置上,不用再進(jìn)行任何比較了吓蘑;如果這個(gè)位置上已經(jīng)有元素了,就調(diào)用它的equals方法與新元素進(jìn)行比較,相同的話就不存了磨镶,不相同就散列其它的地址溃蔫。這樣一來實(shí)際調(diào)用equals方法的次數(shù)就大大降低了,幾乎只需要一兩次琳猫。
10伟叛、String、String StringBu?er 和 StringBuilder 的區(qū)別是什么?
String是只讀字符串脐嫂,它并不是基本數(shù)據(jù)類型统刮,而是一個(gè)對(duì)象。從底層源碼來看是一個(gè)?nal類型的字符數(shù)組雹锣,所引用的字符串不能被改變网沾,一經(jīng)定義,無法再增刪改蕊爵。每次對(duì)String的操作都會(huì)生成新的String對(duì)象辉哥。
private final char value[];
每次+操作 :隱式在堆上new了一個(gè)跟原字符串相同的StringBuilder對(duì)象,再調(diào)用append方法 拼接+后面的字符攒射。
StringBu?er和StringBuilder他們兩都繼承了AbstractStringBuilder抽象類醋旦,從AbstractStringBuilder抽象類中我們可以看到
/**
* The value is used for character storage.
*/
char[] value;
他們的底層都是可變的字符數(shù)組,所以在進(jìn)行頻繁的字符串操作時(shí)会放,建議使用StringBu?er和StringBuilder來進(jìn)行操作饲齐。另外StringBu?er 對(duì)方法加了同步鎖或者對(duì)調(diào)用的方法加了同步鎖,所以是線程安全的咧最。StringBuilder 并沒有對(duì)方法進(jìn)行加同步鎖捂人,所以是非線程安全的。
11矢沿、ArrayList和linkedList的區(qū)別
Array(數(shù)組)是基于索引(index)的數(shù)據(jù)結(jié)構(gòu)滥搭,它使用索引在數(shù)組中搜索和讀取數(shù)據(jù)是很快的。
Array獲取數(shù)據(jù)的時(shí)間復(fù)雜度是O(1),但是要?jiǎng)h除數(shù)據(jù)卻是開銷很大捣鲸,因?yàn)檫@需要重排數(shù)組中的所有數(shù)據(jù),(因?yàn)閯h除數(shù)據(jù)以后, 需要把后面所有的數(shù)據(jù)前移)
缺點(diǎn): 數(shù)組初始化必須指定初始化的長度, 否則報(bào)錯(cuò)
例如:
int[] a = new int[4];
//推介使用int[] 這種方式初始化
int c[] = {23,43,56,78};
//長度:4瑟匆,索引范圍:[0,3]
List—是一個(gè)有序的集合,可以包含重復(fù)的元素栽惶,提供了按索引訪問的方式愁溜,它繼承Collection。
List有兩個(gè)重要的實(shí)現(xiàn)類:ArrayList和LinkedList
ArrayList: 可以看作是能夠自動(dòng)增長容量的數(shù)組
ArrayList的toArray方法返回一個(gè)數(shù)組
ArrayList的asList方法返回一個(gè)列表
ArrayList底層的實(shí)現(xiàn)是Array, 數(shù)組擴(kuò)容實(shí)現(xiàn)
LinkList是一個(gè)雙鏈表,在添加和刪除元素時(shí)具有比ArrayList更好的性能.但在get與set方面弱于
ArrayList.當(dāng)然,這些對(duì)比都是指數(shù)據(jù)量很大或者操作很頻繁外厂。
12冕象、 HashMap和HashTable的區(qū)別
(1)兩者父類不同
HashMap是繼承自AbstractMap類,而Hashtable是繼承自Dictionary類酣衷。不過它們都實(shí)現(xiàn)了同時(shí)實(shí)現(xiàn)了map交惯、Cloneable(可復(fù)制)、Serializable(可序列化)這三個(gè)接口。
(2)對(duì)外提供的接口不同
Hashtable比HashMap多提供了elments() 和contains() 兩個(gè)方法席爽。
elments() 方法繼承自Hashtable的父類Dictionnary意荤。elements() 方法用于返回此Hashtable中的value的枚舉。
contains()方法判斷該Hashtable是否包含傳入的value只锻。它的作用與containsValue()一致玖像。事實(shí)上,contansValue() 就只是調(diào)用了一下contains() 方法齐饮。
(3)對(duì)null的支持不同
Hashtable:key和value都不能為null捐寥。
HashMap:key可以為null,但是這樣的key只能有一個(gè)祖驱,因?yàn)楸仨毐WCkey的唯一性握恳;可以有多個(gè)key值對(duì)應(yīng)的value為null。
(4)安全性不同
HashMap是線程不安全的捺僻,在多線程并發(fā)的環(huán)境下乡洼,可能會(huì)產(chǎn)生死鎖等問題,因此需要開發(fā)人員自己處理多線程的安全問題匕坯。
Hashtable是線程安全的束昵,它的每個(gè)方法上都有synchronized 關(guān)鍵字,因此可直接用于多線程中葛峻。雖然HashMap是線程不安全的锹雏,但是它的效率遠(yuǎn)遠(yuǎn)高于Hashtable,這樣設(shè)計(jì)是合理的术奖,因?yàn)榇蟛糠值氖褂脠鼍岸际菃尉€程礁遵。當(dāng)需要多線程操作的時(shí)候可以使用線程安全的ConcurrentHashMap。
ConcurrentHashMap雖然也是線程安全的采记,但是它的效率比Hashtable要高好多倍榛丢。因?yàn)?/p>
ConcurrentHashMap使用了分段鎖,并不對(duì)整個(gè)數(shù)據(jù)進(jìn)行鎖定挺庞。
(5)計(jì)算hash值的方法不同
13、 Collection包結(jié)構(gòu)稼病,與Collections的區(qū)別
Collection是集合類的上級(jí)接口选侨,子接口有 Set、List然走、LinkedList援制、ArrayList、Vector芍瑞、Stack、Set;Collections是集合類的一個(gè)幫助類洪己, 它包含有各種有關(guān)集合操作的靜態(tài)多態(tài)方法,用于實(shí)現(xiàn)對(duì)各種集合的搜索逝钥、排序拱镐、線程安全化等操作。此類不能實(shí)例化沃琅,就像一個(gè)工具類,服務(wù)于Java的Collection框架益眉。
14晌柬、 Java的四種引用,強(qiáng)弱軟虛
強(qiáng)引用
強(qiáng)引用是平常中使用最多的引用呜叫,強(qiáng)引用在程序內(nèi)存不足(OOM)的時(shí)候也不會(huì)被回收空繁,使用方式:
String str = new String("str");
軟引用
軟引用在程序內(nèi)存不足時(shí),會(huì)被回收朱庆,使用方式:
// 注意:wrf這個(gè)引用也是強(qiáng)引用盛泡,它是指向SoftReference這個(gè)對(duì)象的,
// 這里的軟引用指的是指向new String("str")的引用娱颊,也就是SoftReference類中T
SoftReference<String> wrf = new SoftReference<String>(new String("str"));
可用場景:創(chuàng)建緩存的時(shí)候傲诵,創(chuàng)建的對(duì)象放進(jìn)緩存中,當(dāng)內(nèi)存不足時(shí)箱硕,JVM就會(huì)回收早先創(chuàng)建的對(duì)象拴竹。
弱引用
弱引用就是只要JVM垃圾回收器發(fā)現(xiàn)了它,就會(huì)將之回收剧罩,使用方式:
WeakReference<String> wrf = new WeakReference<String>(str);
可用場景:Java源碼中的 java.util.WeakHashMap中的 key就是使用弱引用栓拜,我的理解就是,一旦我不需要某個(gè)引用惠昔,JVM會(huì)自動(dòng)幫我處理它幕与,這樣我就不需要做其它操作。
虛引用
虛引用的回收機(jī)制跟弱引用差不多镇防,但是它被回收之前啦鸣,會(huì)被放入 ReferenceQueue中。注意哦来氧,其它引用是被JVM回收后才被傳入 ReferenceQueue中的诫给。由于這個(gè)機(jī)制香拉,所以虛引用大多被用于引用銷毀前的處理工作凫碌。還有就是证鸥,虛引用創(chuàng)建的時(shí)候枉层,必須帶有 ReferenceQueue鸟蜡,使用
例子:
PhantomReference<String> prf = new PhantomReference<String>(new
String("str"), new ReferenceQueue<>());
可用場景:對(duì)象銷毀前的一些操作揉忘,比如說資源釋放等泣矛。** Object.finalize()雖然也可以做這類動(dòng)作您朽,但是這個(gè)方式即不安全又低效
15哗总、 泛型常用特點(diǎn) (待補(bǔ)充)
泛型是Java SE 1.5之后的特性讯屈, 《Java 核心技術(shù)》中對(duì)泛型的定義是:
“泛型” 意味著編寫的代碼可以被不同類型的對(duì)象所重用涮母。
“泛型”哈蝇,顧名思義怜跑,“泛指的類型”。我們提供了泛指的概念剧防,但具體執(zhí)行的時(shí)候卻可以有具體的規(guī)則來約束峭拘,比如我們用的非常多的ArrayList就是個(gè)泛型類鸡挠,ArrayList作為集合可以存放各種元素拣展,如Integer, String备埃,自定義的各種類型等按脚,但在我們使用的時(shí)候通過具體的規(guī)則來約束,如我們可以約束集合中只存放Integer類型的元素匪补,如
List<Integer> iniData = new ArrayList<>()
使用泛型的好處蚤氏?
以集合來舉例竿滨,使用泛型的好處是我們不必因?yàn)樘砑釉仡愋偷牟煌x不同類型的集合于游,如整型集合類贰剥,浮點(diǎn)型集合類蚌成,字符串集合類担忧,我們可以定義一個(gè)集合來存放整型最欠、浮點(diǎn)型芝硬,字符串型數(shù)據(jù)吵取,而這并不是最重要的皮官,因?yàn)槲覀冎灰训讓哟鎯?chǔ)設(shè)置了Object即可捺氢,添加的數(shù)據(jù)全部都可向上轉(zhuǎn)型為Object摄乒。更重要的是我們可以通過規(guī)則按照自己的想法控制存儲(chǔ)的數(shù)據(jù)類型。
16梨水、Java創(chuàng)建對(duì)象有幾種方式舅世?
java中提供了以下四種創(chuàng)建對(duì)象的方式:
(1)new創(chuàng)建新對(duì)象
(2)通過反射機(jī)制
(3)采用clone機(jī)制
(4)通過序列化機(jī)制
17雏亚、有沒有可能兩個(gè)不相等的對(duì)象有相同的hashcode
有可能.在產(chǎn)生hash沖突時(shí),兩個(gè)不相等的對(duì)象就會(huì)有相同的 hashcode 值.當(dāng)hash沖突產(chǎn)生時(shí),一般有以下幾種方式來處理:
(1)拉鏈法:每個(gè)哈希表節(jié)點(diǎn)都有一個(gè)next指針,多個(gè)哈希表節(jié)點(diǎn)可以用next指針構(gòu)成一個(gè)單向鏈表罢低,被分配到同一個(gè)索引上的多個(gè)節(jié)點(diǎn)可以用這個(gè)單向鏈表進(jìn)行存儲(chǔ).
(2)開放定址法:一旦發(fā)生了沖突,就去尋找下一個(gè)空的散列地址,只要散列表足夠大,空的散列地址總能找到,并將記錄存入
(3)再哈希:又叫雙哈希法,有多個(gè)不同的Hash函數(shù).當(dāng)發(fā)生沖突時(shí),使用第二個(gè),第三個(gè)….等哈希函數(shù)計(jì)算地址,直到無沖突.
18宜肉、深拷貝和淺拷貝的區(qū)別是什么?
淺拷貝:被復(fù)制對(duì)象的所有變量都含有與原來的對(duì)象相同的值,而所有的對(duì)其他對(duì)象的引用仍然指向原來的對(duì)象.換言之,淺拷貝僅僅復(fù)制所考慮的對(duì)象,而不復(fù)制它所引用的對(duì)象.
深拷貝:被復(fù)制對(duì)象的所有變量都含有與原來的對(duì)象相同的值.而那些引用其他對(duì)象的變量將指向被復(fù)制過的新對(duì)象.而不再是原有的那些被引用的對(duì)象.換言之.深拷貝把要復(fù)制的對(duì)象所引用的對(duì)象都
19、?nal有哪些用法?
?nal也是很多面試喜歡問的地方,但我覺得這個(gè)問題很無聊,通常能回答下以下5點(diǎn)就不錯(cuò)了:
(1)被?nal修飾的類不可以被繼承
(2)被?nal修飾的方法不可以被重寫
(3)被?nal修飾的變量不可以被改變.如果修飾引用,那么表示引用不可變,引用指向的內(nèi)容可變.
(4)被?nal修飾的方法,JVM會(huì)嘗試將其內(nèi)聯(lián),以提高運(yùn)行效率
(5)被?nal修飾的常量,在編譯階段會(huì)存入常量池中.
除此之外,編譯器對(duì)?nal域要遵守的兩個(gè)重排序規(guī)則更好:
在構(gòu)造函數(shù)內(nèi)對(duì)一個(gè)?nal域的寫入,與隨后把這個(gè)被構(gòu)造對(duì)象的引用賦值給一個(gè)引用變量,這兩個(gè)操作之間不能重排序
初次讀一個(gè)包含?nal域的對(duì)象的引用,與隨后初次讀這個(gè)?nal域,這兩個(gè)操作之間不能重排序.
20日杈、static都有哪些用法?
所有的人都知道static關(guān)鍵字這兩個(gè)基本的用法:靜態(tài)變量和靜態(tài)方法.也就是被static所修飾的變量/方法都屬于類的靜態(tài)資源,類實(shí)例所共享.
除了靜態(tài)變量和靜態(tài)方法之外,static也用于靜態(tài)塊,多用于初始化操作:
public calss PreCache{
static{
//執(zhí)行相關(guān)操作
}
}
此外static也多用于修飾內(nèi)部類,此時(shí)稱之為靜態(tài)內(nèi)部類.
最后一種用法就是靜態(tài)導(dǎo)包,即 import static.import static是在JDK 1.5之后引入的新特性,可以用來指定導(dǎo)入某個(gè)類中的靜態(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,因?yàn)橛行└↑c(diǎn)數(shù)不能完全精確的表示出來.
22涨冀、a=a+b與a+=b有什么區(qū)別嗎?
操作符會(huì)進(jìn)行隱式自動(dòng)類型轉(zhuǎn)換,此處a+=b隱式的將加操作的結(jié)果類型強(qiáng)制轉(zhuǎn)換為持有結(jié)果的類型,
byte a = 127;
byte b = 127;
b = a + b;
// 報(bào)編譯錯(cuò)誤:cannot convert from int to byte
b += a;
以下代碼是否有錯(cuò),有的話怎么改鹿鳖?
short s1= 1;
s1 = s1 + 1;
有錯(cuò)誤.short類型在進(jìn)行運(yùn)算時(shí)會(huì)自動(dòng)提升為int類型,也就是說 s1+1的運(yùn)算結(jié)果是int類型,而s1是short類型,此時(shí)編譯器會(huì)報(bào)錯(cuò).
正確寫法:
short s1= 1;
s1 += 1;
+=操作符會(huì)對(duì)右邊的表達(dá)式結(jié)果強(qiáng)轉(zhuǎn)匹配左邊的數(shù)據(jù)類型,所以沒錯(cuò).
23、try catch ?nally涝滴,try里有return歼疮,?nally還執(zhí)行么韩脏?
執(zhí)行骤素,并且?nally的執(zhí)行早于try里面的return
結(jié)論:
(1)不管有木有出現(xiàn)異常济竹,?nally塊中代碼都會(huì)執(zhí)行送浊;
(2)當(dāng)try和catch中有return時(shí)袭景,?nally仍然會(huì)執(zhí)行荒澡;
(3)?nally是在return后面的表達(dá)式運(yùn)算后執(zhí)行的(此時(shí)并沒有返回運(yùn)算后的值单山,而是先把要返回的值保存起來米奸,管?nally中的代碼怎么樣悴晰,返回的值都不會(huì)改變铡溪,任然是之前保存的值)佃却,所以函數(shù)返回值是在?nally執(zhí)行前確定的;
(4)?nally中最好不要包含return瘤泪,否則程序會(huì)提前退出赦邻,返回值不是try或catch中保存的返回值惶洲。
24恬吕、 Excption與Error包結(jié)構(gòu)
Java可拋出(Throwable)的結(jié)構(gòu)分為三種類型:被檢查的異常(CheckedException)铐料,運(yùn)行時(shí)異常(RuntimeException)柒凉,錯(cuò)誤(Error)膝捞。
運(yùn)行時(shí)異常
定義:RuntimeException及其子類都被稱為運(yùn)行時(shí)異常绑警。
特點(diǎn):Java編譯器不會(huì)檢查它。也就是說芽丹,當(dāng)程序中可能出現(xiàn)這類異常時(shí)拔第,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它"逛万,還是會(huì)編譯通過得封。例如忙上,除數(shù)為零時(shí)產(chǎn)生的
ArithmeticException異常疫粥,數(shù)組越界時(shí)產(chǎn)生的IndexOutOfBoundsException異常梗逮,fail-fast機(jī)制產(chǎn)生的ConcurrentModi?cationException異常(java.util包下面的所有的集合類都是快速失敗的库糠,“快速失敗”也就是fail-fast瞬欧,它是Java集合的一種錯(cuò)誤檢測機(jī)制艘虎。當(dāng)多個(gè)線程對(duì)集合進(jìn)行結(jié)構(gòu)上的改變的操作時(shí)野建,有可能會(huì)產(chǎn)生fail-fast機(jī)制候生。記住是有可能须蜗,而不是一定目溉。例如:假設(shè)存在兩個(gè)線程(線程1柿估、線程2)秫舌,線程1通過Iterator在遍歷集合A中的元素舅巷,在某個(gè)時(shí)候線程2修改了集合A的結(jié)構(gòu)(是結(jié)構(gòu)上面的
ConcurrentModi?cationException 異常钠右,從而產(chǎn)生fail-fast機(jī)制飒房,這個(gè)錯(cuò)叫并發(fā)修改異常狠毯。Fail-safe嫡良,java.util.concurrent包下面的所有的類都是安全失敗的献酗,在遍歷過程中很澄,如果已經(jīng)遍歷的數(shù)組上的內(nèi)容變化了甩苛,迭代器不會(huì)拋出ConcurrentModi?cationException異常讯蒲。如果未遍歷的數(shù)組上的內(nèi)容發(fā)生了變化爱葵,則有可能反映到迭代過程中。這就是ConcurrentHashMap迭代器弱一致的表現(xiàn)雷则。ConcurrentHashMap的弱一致性主要是為了提升效率月劈,是一致性與效率之間的一種權(quán)衡猜揪。要成為強(qiáng)一致性而姐,就得到處使用鎖拴念,甚至是全局鎖,這就與Hashtable和同步的HashMap一樣了队魏。)等官帘,都屬于運(yùn)行時(shí)異常遏佣。
常見的五種運(yùn)行時(shí)異常:
(1)ClassCastException(類轉(zhuǎn)換異常)
(2)IndexOutOfBoundsException(數(shù)組越界)
(3)NullPointerException(空指針異常)
(4)ArrayStoreException(數(shù)據(jù)存儲(chǔ)異常意敛,操作數(shù)組是類型不一致)
(5)Bu?erOver?owException
被檢查異常
定義:Exception類本身草姻,以及Exception的子類中除了"運(yùn)行時(shí)異常"之外的其它子類都屬于被檢查異常。
特點(diǎn) : Java編譯器會(huì)檢查它综膀。此類異常剧劝,要么通過throws進(jìn)行聲明拋出讥此,要么通過try-catch進(jìn)行捕獲處理萄喳,否則不能通過編譯。例如闻蛀,CloneNotSupportedException就屬于被檢查異常觉痛。當(dāng)通過clone()接口去克隆一個(gè)對(duì)象薪棒,而該對(duì)象對(duì)應(yīng)的類沒有實(shí)現(xiàn)Cloneable接口俐芯,就會(huì)拋出CloneNotSupportedException異常邮辽。被檢查異常通常都是可以恢復(fù)的吨述。
如:
IOException
FileNotFoundException
SQLException
被檢查的異常適用于那些不是因程序引起的錯(cuò)誤情況,比如:讀取文件時(shí)文件不存在引發(fā)的
FileNotFoundException 邓夕。然而焚刚,不被檢查的異常通常都是由于糟糕的編程引起的,比如:在對(duì)象引
用時(shí)沒有確保對(duì)象非空而引起的 NullPointerException 。
錯(cuò)誤
定義 : Error類及其子類雌团。
特點(diǎn) : 和運(yùn)行時(shí)異常一樣燃领,編譯器也不會(huì)對(duì)錯(cuò)誤進(jìn)行檢查。
當(dāng)資源不足锦援、約束失敗猛蔽、或是其它程序無法繼續(xù)運(yùn)行的條件發(fā)生時(shí),就產(chǎn)生錯(cuò)誤灵寺。程序本身無法修復(fù)這些錯(cuò)誤的曼库。例如,VirtualMachineError就屬于錯(cuò)誤略板。出現(xiàn)這種錯(cuò)誤會(huì)導(dǎo)致程序終止運(yùn)行种玛。OutOfMemoryError、ThreadDeath。
Java虛擬機(jī)規(guī)范規(guī)定JVM的內(nèi)存分為了好幾塊,比如堆,棧,程序計(jì)數(shù)器,方法區(qū)等
25因妇、OOM你遇到過哪些情況灾茁,SOF你遇到過哪些情況
OOM:
(1)OutOfMemoryError異常
Java Heap 溢出:
一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess拓颓。
java堆用于存儲(chǔ)對(duì)象實(shí)例啥繁,我們只要不斷的創(chuàng)建對(duì)象适室,并且保證GC Roots到對(duì)象之間有可達(dá)路徑來避免垃圾回收機(jī)制清除這些對(duì)象汽畴,就會(huì)在對(duì)象數(shù)量達(dá)到最大堆容量限制后產(chǎn)生內(nèi)存溢出異常。
出現(xiàn)這種異常隙券,一般手段是先通過內(nèi)存映像分析工具(如Eclipse Memory Analyzer)對(duì)dump出來的堆轉(zhuǎn)存快照進(jìn)行分析薪铜,重點(diǎn)是確認(rèn)內(nèi)存中的對(duì)象是否是必要的蜒滩,先分清是因?yàn)閮?nèi)存泄漏(Memory Leak)還是內(nèi)存溢出(Memory Over?ow)画株。
如果是內(nèi)存泄漏紧卒,可進(jìn)一步通過工具查看泄漏對(duì)象到GCRoots的引用鏈。于是就能找到泄漏對(duì)象是通過怎樣的路徑與GC Roots相關(guān)聯(lián)并導(dǎo)致垃圾收集器無法自動(dòng)回收。
如果不存在泄漏养葵,那就應(yīng)該檢查虛擬機(jī)的參數(shù)(-Xmx與-Xms)的設(shè)置是否適當(dāng)。
(2)虛擬機(jī)棧和本地方法棧溢出
如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的最大深度,將拋出StackOver?owError異常往果。
如果虛擬機(jī)在擴(kuò)展棧時(shí)無法申請(qǐng)到足夠的內(nèi)存空間局骤,則拋出OutOfMemoryError異常
這里需要注意當(dāng)棧的大小越大可分配的線程數(shù)就越少冰单。
(3)運(yùn)行時(shí)常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGenspace
如果要向運(yùn)行時(shí)常量池中添加內(nèi)容,最簡單的做法就是使用String.intern()這個(gè)Native方法蜓斧。該方法的作用是:如果池中已經(jīng)包含一個(gè)等于此String的字符串帮碰,則返回代表池中這個(gè)字符串的String對(duì)象傻唾;否則扁誓,將此String對(duì)象包含的字符串添加到常量池中,并且返回此String對(duì)象的引用惠桃。由于常量池分配在方法區(qū)內(nèi)续膳,我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區(qū)的大小,從而間接限制其中常量池的容量。
(4)方法區(qū)溢出
方法區(qū)用于存放Class的相關(guān)信息舆声,如類名、訪問修飾符、常量池、字段描述、方法描述等。也有可能是方法區(qū)中保存的class對(duì)象沒有被及時(shí)回收掉或者class信息占用的內(nèi)存超過了我們配置。
異常信息:java.lang.OutOfMemoryError:PermGenspace
方法區(qū)溢出也是一種常見的內(nèi)存溢出異常,一個(gè)類如果要被垃圾收集器回收碘梢,判定條件是很苛刻的搅裙。在經(jīng)常動(dòng)態(tài)生成大量Class的應(yīng)用中甥啄,要特別注意這點(diǎn)。
SOF(堆棧溢出StackOver?ow):
StackOver?owError 的定義:當(dāng)應(yīng)用程序遞歸太深而發(fā)生堆棧溢出時(shí),拋出該錯(cuò)誤。
因?yàn)闂R话隳J(rèn)為1-2m怕膛,一旦出現(xiàn)死循環(huán)或者是大量的遞歸調(diào)用裁僧,在不斷的壓棧過程中贡珊,造成棧容量超過1m而導(dǎo)致溢出。
棧溢出的原因:遞歸調(diào)用涉馁,大量循環(huán)或死循環(huán)门岔,全局變量是否過多,數(shù)組烤送、List寒随、map數(shù)據(jù)過大。
26帮坚、 簡述線程妻往、程序、進(jìn)程的基本概念试和。以及他們之間關(guān)系是什么?
線程與進(jìn)程相似讯泣,但線程是一個(gè)比進(jìn)程更小的執(zhí)行單位。一個(gè)進(jìn)程在其執(zhí)行的過程中可以產(chǎn)生多個(gè)線程阅悍。與進(jìn)程不同的是同類的多個(gè)線程共享同一塊內(nèi)存空間和一組系統(tǒng)資源判帮,所以系統(tǒng)在產(chǎn)生一個(gè)線程局嘁,或是在各個(gè)線程之間作切換工作時(shí),負(fù)擔(dān)要比進(jìn)程小得多晦墙,也正因?yàn)槿绱嗽藐牵€程也被稱為輕量級(jí)進(jìn)程。程序是含有指令和數(shù)據(jù)的文件晌畅,被存儲(chǔ)在磁盤或其他的數(shù)據(jù)存儲(chǔ)設(shè)備中但指,也就是說程序是靜態(tài)的代碼。
進(jìn)程是程序的一次執(zhí)行過程抗楔,是系統(tǒng)運(yùn)行程序的基本單位棋凳,因此進(jìn)程是動(dòng)態(tài)的。系統(tǒng)運(yùn)行一個(gè)程序即是一個(gè)進(jìn)程從創(chuàng)建连躏,運(yùn)行到消亡的過程剩岳。簡單來說,一個(gè)進(jìn)程就是一個(gè)執(zhí)行中的程序入热,它在計(jì)算機(jī)中一個(gè)指令接著一個(gè)指令地執(zhí)行著拍棕,同時(shí),每個(gè)進(jìn)程還占有某些系統(tǒng)資源如 CPU 時(shí)間勺良,內(nèi)存空間绰播,文件,輸入輸出設(shè)備的使用權(quán)等等尚困。換句話說蠢箩,當(dāng)程序在執(zhí)行時(shí),將會(huì)被操作系統(tǒng)載入內(nèi)存中事甜。線程是進(jìn)程劃分成的更小的運(yùn)行單位谬泌。線程和進(jìn)程最大的不同在于基本上各進(jìn)程是獨(dú)立的,而各線程則不一定逻谦,因?yàn)橥贿M(jìn)程中的線程極有可能會(huì)相互影響呵萨。從另一角度來說,進(jìn)程屬于操作系統(tǒng)的范疇跨跨,主要是同一段時(shí)間內(nèi)潮峦,可以同時(shí)執(zhí)行一個(gè)以上的程序,而線程則是在同一程序內(nèi)幾乎同時(shí)執(zhí)行一個(gè)以上的程序段勇婴。
27忱嘹、線程有哪些基本狀態(tài)?(補(bǔ)充)
Java 線程在運(yùn)行的生命周期中的指定時(shí)刻只可能處于下面 6 種不同狀態(tài)的其中一個(gè)狀態(tài)(圖源《Java并發(fā)編程藝術(shù)》4.1.4 節(jié))。
28耕渴、Java 序列化中如果有些字段不想進(jìn)行序列化拘悦,怎么辦?
對(duì)于不想進(jìn)行序列化的變量橱脸,使用 transient 關(guān)鍵字修飾础米。
transient 關(guān)鍵字的作用是:阻止實(shí)例中那些用此關(guān)鍵字修飾的的變量序列化分苇;當(dāng)對(duì)象被反序列化時(shí),被 transient 修飾的變量值不會(huì)被持久化和恢復(fù)屁桑。transient 只能修飾變量医寿,不能修飾類和方法。
29蘑斧、Java 中 IO 流
Java 中 IO 流分為幾種?
(1)按照流的流向分靖秩,可以分為輸入流和輸出流;
(2)按照操作單元?jiǎng)澐质梢詣澐譃樽止?jié)流和字符流沟突;
(3)按照流的角色劃分為節(jié)點(diǎn)流和處理流。
Java Io 流共涉及 40 多個(gè)類捕传,這些類看上去很雜亂惠拭,但實(shí)際上很有規(guī)則,而且彼此之間存在非常緊密的聯(lián)系庸论, Java I0 流的 40 多個(gè)類都是從如下 4 個(gè)抽象類基類中派生出來的职辅。
InputStream/Reader: 所有的輸入流的基類,前者是字節(jié)輸入流葡公,后者是字符輸入流罐农。
OutputStream/Writer: 所有輸出流的基類条霜,前者是字節(jié)輸出流催什,后者是字符輸出流。
按操作方式分類結(jié)構(gòu)圖:
按操作對(duì)象分類結(jié)構(gòu)圖:
30宰睡、 Java IO與 NIO的區(qū)別(補(bǔ)充)
NIO即New IO蒲凶,這個(gè)庫是在JDK1.4中才引入的。NIO和IO有相同的作用和目的拆内,但實(shí)現(xiàn)方式不同旋圆,NIO主要用到的是塊,所以NIO的效率要比IO高很多麸恍。在Java API中提供了兩套NIO灵巧,一套是針對(duì)標(biāo)準(zhǔn)輸入輸出NIO,另一套就是網(wǎng)絡(luò)編程N(yùn)IO抹沪。
31刻肄、java反射的作用于原理
(1)定義:
反射機(jī)制是在運(yùn)行時(shí),對(duì)于任意一個(gè)類融欧,都能夠知道這個(gè)類的所有屬性和方法敏弃;對(duì)于任意個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法噪馏。在java中麦到,只要給定類的名字绿饵,就可以通過反射機(jī)制來獲得類的所有信息。
這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語言的反射機(jī)制瓶颠。
(2)哪里會(huì)用到反射機(jī)制拟赊?
jdbc就是典型的反射
Class.forName('com.mysql.jdbc.Driver.class');
//加載MySQL的驅(qū)動(dòng)類
這就是反射。如hibernate步清,struts等框架使用反射實(shí)現(xiàn)的要门。
第一步:獲取Class對(duì)象,有4中方法:
1)Class.forName(“類的路徑”)廓啊;
2)類名.class
3)對(duì)象名.getClass()
4)基本類型的包裝類欢搜,可以調(diào)用包裝類的Type屬性來獲得該包裝類的Class對(duì)象
(3)實(shí)現(xiàn)Java反射的類:
1)Class:表示正在運(yùn)行的Java應(yīng)用程序中的類和接口
注意:所有獲取對(duì)象的信息都需要Class類來實(shí)現(xiàn)。
2)Field:提供有關(guān)類和接口的屬性信息谴轮,以及對(duì)它的動(dòng)態(tài)訪問權(quán)限炒瘟。
3)Constructor:提供關(guān)于類的單個(gè)構(gòu)造方法的信息以及它的訪問權(quán)限
4)Method:提供類或接口中某個(gè)方法的信息
(4)反射機(jī)制的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
1)能夠運(yùn)行時(shí)動(dòng)態(tài)獲取類的實(shí)例,提高靈活性第步;
2)與動(dòng)態(tài)編譯結(jié)合
缺點(diǎn):
1)使用反射性能較低疮装,需要解析字節(jié)碼,將內(nèi)存中的對(duì)象進(jìn)行解析粘都。
解決方案:
1廓推、通過setAccessible(true)關(guān)閉JDK的安全檢查來提升反射速度;
2翩隧、多次創(chuàng)建一個(gè)類的實(shí)例時(shí)樊展,有緩存會(huì)快很多
3、Re?ectASM工具類堆生,通過字節(jié)碼生成的方式加快反射速度
2)相對(duì)不安全专缠,破壞了封裝性(因?yàn)橥ㄟ^反射可以獲得私有方法和屬性)
32、說說List,Set,Map三者的區(qū)別淑仆?
List(對(duì)付順序的好幫手):List接口存儲(chǔ)一組不唯一(可以有多個(gè)元素引用相同的對(duì)象)涝婉,有序的對(duì)象
Set(注重獨(dú)一無二的性質(zhì)): 不允許重復(fù)的集合。不會(huì)有多個(gè)元素引用相同的對(duì)象蔗怠。
Map(用Key來搜索的專家): 使用鍵值對(duì)存儲(chǔ)墩弯。Map會(huì)維護(hù)與Key有關(guān)聯(lián)的值。兩個(gè)Key可以引用相同的對(duì)象寞射,但Key不能重復(fù)渔工,典型的Key是String類型,但也可以是任何對(duì)象怠惶。
最后
私信回復(fù) 資料 領(lǐng)取一線大廠Java面試題總結(jié)+各知識(shí)點(diǎn)學(xué)習(xí)思維導(dǎo)+一份300頁pdf文檔的Java核心知識(shí)點(diǎn)總結(jié)涨缚!
這些資料的內(nèi)容都是面試時(shí)面試官必問的知識(shí)點(diǎn),篇章包括了很多知識(shí)點(diǎn),其中包括了有基礎(chǔ)知識(shí)脓魏、Java集合兰吟、JVM、多線程并發(fā)茂翔、spring原理混蔼、微服務(wù)、Netty 與RPC 珊燎、Kafka惭嚣、日記、設(shè)計(jì)模式悔政、Java算法晚吞、數(shù)據(jù)庫、Zookeeper谋国、分布式緩存槽地、數(shù)據(jù)結(jié)構(gòu)等等。