轉(zhuǎn)載請(qǐng)注明出處:http://blog.csdn.net/zhoubin1992/article/details/46481759
在Android編程或者面試中經(jīng)常會(huì)遇到Java 面向?qū)ο蠛图系闹R(shí)點(diǎn)。自己結(jié)合實(shí)際的編程以及閱讀網(wǎng)上資料總結(jié)一下竟秫。
java面向?qū)ο?萬(wàn)物皆為對(duì)象
一秘案、==和equal()的區(qū)別
1额各、基本數(shù)據(jù)類型: byte,short,char,int,long,float,double,boolean 他們之間的比較睦尽,應(yīng)用雙等號(hào)(==),比較的是他們的值脏答。
2碗暗、復(fù)合數(shù)據(jù)類型(類) :當(dāng)他們用(==)進(jìn)行比較的時(shí)候抱虐,比較的是他們?cè)贘VM中的存放地址昌阿,所以,除非是同一個(gè)new出來(lái)的對(duì)象恳邀,他們的比較后的結(jié)果為true宝泵,否則比較后結(jié)果為false。 JAVA當(dāng)中所有的類都是繼承于Object這個(gè)基類的轩娶,在Object中的基類中定義了一個(gè)equals的方法儿奶,這個(gè)方法的初始行為也是比較對(duì)象的內(nèi)存地址,但在一些類庫(kù)當(dāng)中這個(gè)方法被覆蓋掉了鳄抒,如String,Integer,Date在這些類當(dāng)中equals有其自身的實(shí)現(xiàn)闯捎,而不再是比較類在堆內(nèi)存中的存放地址了。
3许溅、String的equal()
(1)String類中的equals首先比較地址瓤鼻,如果是同一個(gè)對(duì)象的引用,可知對(duì)象相等贤重,返回true茬祷。
(2)若果不是同一個(gè)對(duì)象,equals方法挨個(gè)比較兩個(gè)字符串對(duì)象內(nèi)的字符并蝗,只有完全相等才返回true祭犯,否則返回false。
二滚停、String沃粗、StringBuffer、StringBuilder的區(qū)別
String 字符串常量(對(duì)象不可變键畴,線程安全) private final char value[];
StringBuffer 字符串變量(線程安全)
StringBuilder 字符串變量(非線程安全) char[] value;
如果程序不是多線程的最盅,那么使用StringBuilder效率高于StringBuffer。
在大部分情況下運(yùn)行效率:StringBuilder > StringBuffer> String
三、final, finally, finalize的區(qū)別
final 用于聲明屬性涡贱,方法和類咏删,分別表示屬性不可變,方法不可覆蓋问词,類不可繼承督函。
finally是異常處理語(yǔ)句結(jié)構(gòu)的一部分,表示總是執(zhí)行戏售。
finalize是Object類的一個(gè)方法,在垃圾收集器執(zhí)行的時(shí)候會(huì)調(diào)用被回收對(duì)象的此方法草穆,可以覆蓋此方法提供垃圾收集時(shí)的其他資源回收灌灾,例如關(guān)閉文件等。
四悲柱、Overload和Override的區(qū)別
方法的重寫Overriding和重載Overloading是Java多態(tài)性的不同表現(xiàn)锋喜。重寫Overriding是父類與子類之間多態(tài)性的一種表現(xiàn),重載Overloading是一個(gè)類中多態(tài)性的一種表現(xiàn)豌鸡。如果在子類中定義某方法與其父類有相同的名稱和參數(shù)嘿般,我們說(shuō)該方法被重寫 (Overriding)。子類的對(duì)象使用這個(gè)方法時(shí)涯冠,將調(diào)用子類中的定義炉奴,對(duì)它而言,父類中的定義如同被”屏蔽”了蛇更。如果在一個(gè)類中定義了多個(gè)同名的方法瞻赶,它們或有不同的參數(shù)個(gè)數(shù)或有不同的參數(shù)類型,則稱為方法的重載(Overloading)派任。
五砸逊、java 繼承
extends關(guān)鍵字,子類擴(kuò)展了父類掌逛,也具有父類的全部成員變量和方法师逸,但是Java的子類不能獲得父類的構(gòu)造器。 Java沒(méi)有C++中的多繼承特征豆混,每個(gè)類最多只有一個(gè)直接父類(單繼承) 當(dāng)調(diào)用子類構(gòu)造器來(lái)初始化子類對(duì)象時(shí)篓像,父類構(gòu)造器總會(huì)在子類構(gòu)造器之前執(zhí)行。 創(chuàng)建任何Java對(duì)象皿伺,最先執(zhí)行的總是java.lang.object類的構(gòu)造器遗淳,從該類所在繼承樹(shù)最頂層類的構(gòu)造器開(kāi)始執(zhí)行,然后依次向下執(zhí)行心傀。
六屈暗、Java多態(tài)
如果Java引用變量的編譯時(shí)類型和運(yùn)行時(shí)類型不一致是,就可能出現(xiàn)多態(tài)。 運(yùn)行時(shí)該引用變量的方法總是表現(xiàn)出子類方法的行為特征养叛。(出現(xiàn)重寫) Java中多態(tài)的實(shí)現(xiàn)方式:接口實(shí)現(xiàn)种呐,繼承父類進(jìn)行方法重寫(父類引用指向子類對(duì)象),同一個(gè)類中進(jìn)行方法重載弃甥。
七爽室、抽象類和接口的區(qū)別
接口和抽象類的概念不一樣。接口是對(duì)動(dòng)作的抽象(吃)淆攻,抽象類是對(duì)根源的抽象(人)阔墩。 一個(gè)類只能繼承一個(gè)類(抽象類),但是可以實(shí)現(xiàn)多個(gè)接口(吃瓶珊,行)啸箫。 1. 接口可以多繼承,抽象類不行 2. 抽象類中可以定義一些子類的公共方法伞芹,子類只需要增加新的功能忘苛,不需要重復(fù)寫已經(jīng)存在的方法;而接口中只是對(duì)方法的申明和常量的定義唱较。 3. 接口中基本數(shù)據(jù)類型為public static 而抽類象不是扎唾,是普通變量類型。 4. 抽象類和接口都不能直接實(shí)例化南缓,如果要實(shí)例化胸遇,抽象類變量必須指向?qū)崿F(xiàn)所有抽象方法的子類對(duì)象,接口變量必須指向?qū)崿F(xiàn)所有接口方法的類對(duì)象汉形。 5. 抽象類里的抽象方法必須全部被子類所實(shí)現(xiàn)狐榔,如果子類不能全部實(shí)現(xiàn)父類抽象方法,那么該子類只能是抽象類获雕。同樣薄腻,一個(gè)實(shí)現(xiàn)接口的時(shí)候,如不能全部實(shí)現(xiàn)接口方法届案,那么該類也只能為抽象類庵楷。
八、內(nèi)部類作用
放在一個(gè)類的內(nèi)部的類我們就叫內(nèi)部類楣颠。
作用:
- 內(nèi)部類可以很好的實(shí)現(xiàn)隱藏尽纽,方便將存在一定邏輯關(guān)系的類組織在一起。 一般的非內(nèi)部類童漩,是不允許有private與protected權(quán)限的弄贿,但內(nèi)部類可以。
- 內(nèi)部類擁有外圍類的所有元素的訪問(wèn)權(quán)限矫膨。
- 可是實(shí)現(xiàn)多重繼承差凹,每個(gè)內(nèi)部類都能獨(dú)立的繼承一個(gè)接口的實(shí)現(xiàn)期奔,所以無(wú)論外部類是否已經(jīng)繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)于內(nèi)部類都沒(méi)有影響危尿。內(nèi)部類使得多繼承的解決方案變得完整呐萌。
- 可以避免修改接口而實(shí)現(xiàn)同一個(gè)類中兩種同名方法的調(diào)用。
- 方便編寫線程代碼谊娇。
九肺孤、java對(duì)象序列化
序列化:把Java對(duì)象轉(zhuǎn)換為字節(jié)序列的過(guò)程。
反序列化:把字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程济欢。
只有實(shí)現(xiàn)了Serializable和Externalizable接口的類的對(duì)象才能被序列化赠堵。 讀取對(duì)象的順序與寫入時(shí)的順序要一致。 對(duì)象的默認(rèn)序列化機(jī)制寫入的內(nèi)容是:對(duì)象的類法褥,類簽名茫叭,以及非瞬態(tài)和非靜態(tài)字段的值。
用途 :
1) 把對(duì)象轉(zhuǎn)換成平臺(tái)無(wú)關(guān)的二進(jìn)制流永久地保存到硬盤上挖胃,通常存放在一個(gè)文件中杂靶;
2) 在網(wǎng)絡(luò)上傳送對(duì)象的字節(jié)序列梆惯。
十酱鸭、java集合
HashSet類
hashSet用Hash算法來(lái)存儲(chǔ)集合中的元素,具有很好的存取和查找性能垛吗。
特點(diǎn):
- 無(wú)序
- 不是同步的
- 集合元素值可為null
- 不允許包含相同的元素
存入一個(gè)元素: HashSet調(diào)用該對(duì)象的hashCode()方法得到hashCode值凹髓,根據(jù)該hashCode值確定該對(duì)象的存儲(chǔ)位置。
訪問(wèn)一個(gè)元素: HashSet先計(jì)算該元素的hashCode值怯屉,然后直接到該hashCode值對(duì)應(yīng)的位置去取出該元素蔚舀。 如果元素相同則添加失敗add()返回false。
HashSet集合判斷兩個(gè)元素相同的標(biāo)準(zhǔn)是兩個(gè)對(duì)象equals()方法比較相等锨络,并且hashCode值也相等赌躺。
如果兩個(gè)對(duì)象的hashCode值相同,equals()返回false時(shí)羡儿,會(huì)在同一個(gè)位置用鏈?zhǔn)浇Y(jié)構(gòu)來(lái)保存礼患。導(dǎo)致性能下降。
十一掠归、ArrayList和Vector有何異同點(diǎn)
相同點(diǎn):
- 兩者都是基于索引的缅叠,內(nèi)部由一個(gè)數(shù)組支持。
- 兩者維護(hù)插入的順序虏冻,我們可以根據(jù)插入順序來(lái)獲取元素肤粱。
- ArrayList和Vector的迭代器實(shí)現(xiàn)都是fail-fast的。
- ArrayList和Vector兩者允許null值厨相,也可以使用索引值對(duì)元素進(jìn)行隨機(jī)訪問(wèn)领曼。
不同點(diǎn):
- Vector是同步的鸥鹉,而ArrayList不是。然而悯森,如果你尋求在迭代的時(shí)候?qū)α斜磉M(jìn)行改變宋舷,你應(yīng)該使用CopyOnWriteArrayList。
- ArrayList比Vector快瓢姻,它因?yàn)橛型阶r穑粫?huì)過(guò)載。
- ArrayList更加通用幻碱,因?yàn)槲覀兛梢允褂肅ollections工具類輕易地獲取同步列表和只讀列表绎狭。
十二、HashMap類和Hashtable類
??HashMap和Hashtable判斷兩個(gè)key相等的標(biāo)準(zhǔn)是兩個(gè)key的equals()方法比較返回true褥傍,并且hashCode值也相等儡嘶。 對(duì)同一個(gè)Key,只會(huì)有一個(gè)對(duì)應(yīng)的value值存在恍风。 如何算是同一個(gè)Key蹦狂? 首先,兩個(gè)key對(duì)象的hash值相同朋贬,其次凯楔,key對(duì)象的equals方法返回真 所以用做key的對(duì)象必須重寫equals()和hashCode()方法,保證兩個(gè)方法的判斷標(biāo)準(zhǔn)一致——兩個(gè)key的equals方法返回真锦募,hashCode值也相同摆屯。
HashMap和Hashtable的區(qū)別
HashMap允許key和value為null,而HashTable不允許糠亩。HashTable是同步的(線程安全)虐骑,而HashMap不是(線程不安全)。所以HashMap適合單線程環(huán)境赎线,HashTable適合多線程環(huán)境廷没。HashMap比HashTable的性能高點(diǎn)。
HashMap和Hashtable中key-value對(duì)無(wú)序垂寥。但在Java1.4中引入了LinkedHashMap颠黎,HashMap的一個(gè)子類,假如你想要遍歷順序矫废,你很容易從HashMap轉(zhuǎn)向LinkedHashMap盏缤,但是HashTable不是這樣的,它的順序是不可預(yù)知的蓖扑。
HashMap提供對(duì)key的Set進(jìn)行iterator遍歷唉铜,因此它是fail-fast的,但Hashtable提供對(duì)key的Enumeration進(jìn)行遍歷律杠,它不支持fail-fast潭流。(fail-fast 機(jī)制是java集合(Collection)中的一種錯(cuò)誤機(jī)制竞惋。當(dāng)多個(gè)線程對(duì)同一個(gè)集合的內(nèi)容進(jìn)行操作時(shí),就可能會(huì)產(chǎn)生fail-fast事件灰嫉。例如:當(dāng)某一個(gè)線程A通過(guò)iterator去遍歷某集合的過(guò)程中拆宛,若該集合的內(nèi)容被其他線程所改變了;那么線程A訪問(wèn)集合時(shí)讼撒,就會(huì)拋出ConcurrentModificationException異常浑厚,產(chǎn)生fail-fast事件)Hashtable被認(rèn)為是個(gè)遺留的類,如果你尋求在迭代的時(shí)候修改Map根盒,你應(yīng)該使用CocurrentHashMap钳幅。HashTable中hash數(shù)組默認(rèn)大小是11,增加的方式是 old*2+1炎滞。HashMap中hash數(shù)組的默認(rèn)大小是16敢艰,而且一定是2的指數(shù)。
hashCode()和equals()方法有何重要性
hashCode是根類Obeject中的方法册赛。 默認(rèn)情況下钠导,Object中的hashCode() 返回對(duì)象的32位jvm內(nèi)存地址。也就是說(shuō)如果對(duì)象不重寫該方法森瘪,則返回相應(yīng)對(duì)象的32為JVM內(nèi)存地址牡属。
HashMap使用Key對(duì)象的hashCode()和equals()方法去決定key-value對(duì)的索引。當(dāng)我們?cè)囍鴱腍ashMap中獲取值的時(shí)候柜砾,這些方法也會(huì)被用到湃望。如果這些方法沒(méi)有被正確地實(shí)現(xiàn)换衬,在這種情況下痰驱,兩個(gè)不同Key也許會(huì)產(chǎn)生相同的hashCode()和equals()輸出,HashMap將會(huì)認(rèn)為它們是相同的瞳浦,然后覆蓋它們担映,而非把它們存儲(chǔ)到不同的地方。同樣的叫潦,所有不允許存儲(chǔ)重復(fù)數(shù)據(jù)的集合類都使用hashCode()和equals()去查找重復(fù)蝇完,所以正確實(shí)現(xiàn)它們非常重要。equals()和hashCode()的實(shí)現(xiàn)應(yīng)該遵循以下規(guī)則: 2.1 如果o1.equals(o2)矗蕊,那么o1.hashCode() == o2.hashCode()總是為true的短蜕。 2.2 如果o1.hashCode() == o2.hashCode(),并不意味著o1.equals(o2)會(huì)為true傻咖。
*在Java中朋魔,HashMap是如何工作的?
??HashMap在Map.Entry靜態(tài)內(nèi)部類實(shí)現(xiàn)中存儲(chǔ)key-value對(duì)卿操。HashMap使用哈希算法警检,在put和get方法中孙援,它使用hashCode()和equals()方法。當(dāng)我們通過(guò)傳遞key-value對(duì)調(diào)用put方法的時(shí)候扇雕,HashMap使用Key hashCode()和哈希算法來(lái)找出存儲(chǔ)key-value對(duì)的索引拓售。Entry存儲(chǔ)在LinkedList中,所以如果存在entry镶奉,它使用equals()方法來(lái)檢查傳遞的key是否已經(jīng)存在础淤,如果存在,它會(huì)覆蓋value哨苛,如果不存在值骇,它會(huì)創(chuàng)建一個(gè)新的entry然后保存。當(dāng)我們通過(guò)傳遞key調(diào)用get方法時(shí)移国,它再次使用hashCode()來(lái)找到數(shù)組中的索引吱瘩,然后使用equals()方法找出正確的Entry,然后返回它的值迹缀。 其它關(guān)于HashMap比較重要的問(wèn)題是容量使碾、負(fù)荷系數(shù)和閥值調(diào)整。HashMap默認(rèn)的初始容量是32祝懂,負(fù)荷系數(shù)是0.75票摇。閥值是為負(fù)荷系數(shù)乘以容量,無(wú)論何時(shí)我們嘗試添加一個(gè)entry砚蓬,如果map的大小比閥值大的時(shí)候矢门,HashMap會(huì)對(duì)map的內(nèi)容進(jìn)行重新哈希,且使用更大的容量灰蛙。容量總是2的冪祟剔,所以如果你知道你需要存儲(chǔ)大量的key-value對(duì),比如緩存從數(shù)據(jù)庫(kù)里面拉取的數(shù)據(jù)摩梧,使用正確的容量和負(fù)荷系數(shù)對(duì)HashMap進(jìn)行初始化是個(gè)不錯(cuò)的做法物延。