學(xué)習(xí)啦 > 創(chuàng)業(yè)指南 > 職場 > 面試題 > 阿里JAVA開發(fā)面試常問問題

阿里JAVA開發(fā)面試常問問題

時間: 護托1061 分享

阿里JAVA開發(fā)面試常問問題

  Java中沒有虛函數(shù)的概念。它的普通函數(shù)就相當(dāng)于c++的虛函數(shù),動態(tài)綁定是java的默認(rèn)行為。下面就由學(xué)習(xí)啦小編為大家介紹一下阿里JAVA開發(fā)面試常問問題的文章,歡迎閱讀。

  阿里JAVA開發(fā)面試常問問題篇1

  棧內(nèi)存、堆內(nèi)存

  在函數(shù)中定義的一些基本類型的變量和對象的引用變量都是在函數(shù)的棧內(nèi)存中分配。當(dāng)在一段代碼塊中定義一個變量時,java就在棧中為這個變量分配內(nèi)存空間,當(dāng)超過變量的作用域后,java會自動釋放掉為該變量分配的內(nèi)存空間,該內(nèi)存空間可以立刻被另作他用。

  堆內(nèi)存用于存放由new創(chuàng)建的對象和數(shù)組。在堆中分配的內(nèi)存,由java虛擬機自動垃圾回收器來管理。在數(shù)組和對象在沒有引用變量指向它的時候,才變成垃圾,不能再被使用,但是仍然占著內(nèi)存,在隨后的一個不確定的時間被垃圾回收器釋放掉。這個也是java比較占內(nèi)存的主要原因。

  引用、值傳遞

  值傳遞:方法調(diào)用時,實際參數(shù)把它的值傳遞給對應(yīng)的形式參數(shù),方法執(zhí)行中形式參數(shù)值的改變不影響實際參數(shù)的值。

  引用傳遞:也稱為傳地址。方法調(diào)用時,實際參數(shù)的引用(地址,而不是參數(shù)的值)被傳遞給方法中相對應(yīng)的形式參數(shù),在方法執(zhí)行中,對形式參數(shù)的操作實際上就是對實際參數(shù)的操作,方法執(zhí)行中形式參數(shù)值的改變將會影響實際參數(shù)的值。

  單例模式及好處

  構(gòu)造函數(shù)私有化,用一個靜態(tài)方法來獲取對象實例。

  特點:

  1)單例類只能有一個實例。

  2)單例類必須自己創(chuàng)建自己的唯一實例。

  3)單例類必須給所有其他對象提供這一實例。

  主要優(yōu)點:

  1)提供了對唯一實例的受控訪問。

  2)由于在系統(tǒng)內(nèi)存中只存在一個對象,因此可以節(jié)約系統(tǒng)資源,對于一些需要頻繁創(chuàng)建和銷毀的對象單例模式無疑可以提高系統(tǒng)的性能。

  3)允許可變數(shù)目的實例。

  主要缺點:

  1)由于單利模式中沒有抽象層,因此單例類的擴展有很大的困難。

  2)單例類的職責(zé)過重,在一定程度上違背了“單一職責(zé)原則”。

  3)濫用單例將帶來一些負(fù)面問題,如為了節(jié)省資源將數(shù)據(jù)庫連接池對象設(shè)計為的單例類,可能會導(dǎo)致共享連接池對象的程序過多而出現(xiàn)連接池溢出;如果實例化的對象長時間不被利用,系統(tǒng)會認(rèn)為是垃圾而被回收,這將導(dǎo)致對象狀態(tài)的丟失。

  阿里JAVA開發(fā)面試常問問題篇2

  重載和重寫

  重載:Overloading

  (1) Java的方法重載,就是在類中可以創(chuàng)建多個方法,它們具有相同的名字,但具有不同的參數(shù)和不同的定義。調(diào)用方法時通過傳遞給它們的不同參數(shù)個數(shù)和參數(shù)類型來決定具體使用哪個方法, 這就是多態(tài)性。

  (2) 重載的時候,方法名要一樣,但是參數(shù)類型和個數(shù)不一樣,返回值類型可以相同也可以不相同。無法以返回類型作為重載函數(shù)的區(qū)分標(biāo)準(zhǔn)。

  重寫:Overriding

  注意:當(dāng)要重寫父類方法時,要使用@Override標(biāo)簽提醒編譯器檢查代碼是否是重寫,而不是重載了原來的方法。

  (1) 父類與子類之間的多態(tài)性,對父類的函數(shù)進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和參數(shù),我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類并不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋。

  (2)若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數(shù)表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關(guān)鍵字,該關(guān)鍵字引用了當(dāng)前類的父類。

  (3)子類函數(shù)的訪問修飾權(quán)限不能少于父類的。

  子類、父類間的轉(zhuǎn)換和構(gòu)造順序

  子類、父類間的轉(zhuǎn)換:

  子類能夠自動轉(zhuǎn)換成父類類型。

  當(dāng)創(chuàng)建子類對象的時候:

 ?、傧日{(diào)用了子類的構(gòu)造函數(shù)

 ?、谡{(diào)用了父類的構(gòu)造函數(shù)

  ③執(zhí)行了父類的構(gòu)造函數(shù)

 ?、軋?zhí)行了子類的構(gòu)造函數(shù)

  Final、finally、finalize

  final 用于聲明屬性,方法和類,分別表示屬性不可變,方法不可覆蓋,類不可繼承。

  finally是異常處理語句結(jié)構(gòu)的一部分,表示總是執(zhí)行。

  finalize是Object類的一個方法,在垃圾收集器執(zhí)行的時候會調(diào)用被回收對象的此方法,可以覆蓋此方法提供垃圾收集時的其他資源回收,例如關(guān)閉文件等

  Synchronized和volatile的區(qū)別

  volatile只作用于在多個線程之間能夠被共享的變量。如果一個字段被聲明成volatile,java線程內(nèi)存模型確保所有線程看到這個變量的值是一致的。Volatile變量修飾符如果使用恰當(dāng)?shù)脑?,它比synchronized的使用和執(zhí)行成本會更低,因為它不會引起線程上下文的切換和調(diào)度。

  synchronized獲得并釋放監(jiān)視器——如果兩個線程使用了同一個對象鎖,監(jiān)視器能強制保證代碼塊同時只被一個線程所執(zhí)行——這是眾所周知的事實。但是,synchronized也同步內(nèi)存:事實上,synchronized在“ 主”內(nèi)存區(qū)域同步整個線程的內(nèi)存。

  因此volatile只是在線程內(nèi)存和“主”內(nèi)存間同步某個變量的值,而synchronized通過鎖定和解鎖某個監(jiān)視器同步所有變量的值。顯然synchronized要比volatile消耗更多資源。

  1)volatile本質(zhì)是在告訴jvm當(dāng)前變量在寄存器(工作內(nèi)存)中的值是不確定的,需要從主存中讀取,沒有互斥鎖;synchronized則是鎖定當(dāng)前變量,只有當(dāng)前線程可以訪問該變量,其他線程被阻塞住。

  2)volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別的

  3)volatile只是在線程內(nèi)存和“主”內(nèi)存間同步某個變量的值,而synchronized通過鎖定和解鎖某個監(jiān)視器同步所有變量的值;顯然synchronized要比volatile消耗更多資源。

  4)volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。

  5)volatile標(biāo)記的變量不會被編譯器優(yōu)化;synchronized標(biāo)記的變量可以被編譯器優(yōu)化 。

  阿里JAVA開發(fā)面試常問問題篇3

  集合類沒有實現(xiàn)Cloneable和Serializable接口的原因

  Collection接口指定一組對象,對象即為它的元素。如何維護這些元素由Collection的具體實現(xiàn)決定。例如,一些如List的Collection實現(xiàn)允許重復(fù)的元素,而其它的如Set就不允許。很多Collection實現(xiàn)有一個公有的clone方法。然而,把它放到集合的所有實現(xiàn)中也是沒有意義的。這是因為Collection是一個抽象表現(xiàn)。重要的是實現(xiàn)。

  當(dāng)與具體實現(xiàn)打交道的時候,克隆或序列化的語義和含義才發(fā)揮作用。所以,具體實現(xiàn)應(yīng)該決定如何對它進行克隆或序列化,或它是否可以被克隆或序列化。

  在所有的實現(xiàn)中授權(quán)克隆和序列化,最終導(dǎo)致更少的靈活性和更多的限制。特定的實現(xiàn)應(yīng)該決定它是否可以被克隆和序列化。

  hashCode()和equals()方法的重要性體現(xiàn)在什么地方?

  HashMap使用Key對象的hashCode()和equals()方法去決定key-value對的索引。當(dāng)我們試著從HashMap中獲取值的時候,這些方法也會被用到。如果這些方法沒有被正確地實現(xiàn),在這種情況下,兩個不同Key也許會產(chǎn)生相同的hashCode()和equals()輸出,HashMap將會認(rèn)為它們是相同的,然后覆蓋它們,而非把它們存儲到不同的地方。同樣的,所有不允許存儲重復(fù)數(shù)據(jù)的集合類都使用hashCode()和equals()去查找重復(fù),所以正確實現(xiàn)它們非常重要。

  equals()和hashCode()的實現(xiàn)應(yīng)該遵循以下規(guī)則:

  (1)如果o1.equals(o2),那么o1.hashCode() == o2.hashCode()總是為true的。

  (2)如果o1.hashCode() == o2.hashCode(),并不意味著o1.equals(o2)會為true。

  Java中的HashMap使用hashCode()和equals()方法來確定鍵值對的索引,當(dāng)根據(jù)鍵獲取值的時候也會用到這兩個方法。如果沒有正確的實現(xiàn)這兩個方法,兩個不同的鍵可能會有相同的hash值,因此,可能會被集合認(rèn)為是相等的。而且,這兩個方法也用來發(fā)現(xiàn)重復(fù)元素。所以這兩個方法的實現(xiàn)對HashMap的精確性和正確性是至關(guān)重要的。

  HashMap和HashTabel的區(qū)別

  HashMap和Hashtable都實現(xiàn)了Map接口,因此很多特性非常相似。但是,他們有以下不同點:

  1)HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。

  2)Hashtable是同步的,而HashMap不是。因此,HashMap更適合于單線程環(huán)境,而Hashtable適合于多線程環(huán)境。

  3)HashMap提供了可供應(yīng)用迭代的鍵的集合,因此,HashMap是快速失敗的。另一方面,Hashtable提供了對鍵的列舉(Enumeration)。

  一般認(rèn)為Hashtable是一個遺留的類。

  Comparable和Comparator接口

  Comparable和Comparator都是用來實現(xiàn)集合中的排序的,只是Comparable是在集合內(nèi)部定義的方法實現(xiàn)的排序,Comparator是在集合外部實現(xiàn)的排序,所以,如想實現(xiàn)排序,就需要在集合外定義Comparator接口的方法compare()或在集合內(nèi)實現(xiàn)Comparable接口的方法compareTo()。

  comparable是支持自比較,而后者是支持外部比較;

  Comparable是一個對象本身就已經(jīng)支持自比較所需要實現(xiàn)的接口(如String、Integer自己就可以完成比較大小操作)

  而Comparator是一個專用的比較器,當(dāng)這個對象不支持自比較或者自比較函數(shù)不能滿足你的要求時,你可以寫一個比較器來完成兩個對象之間大小的比較。

  也就是說當(dāng)你需要對一個自定義的類的一個數(shù)組或者集合進行比較的時候可以實現(xiàn)Comparable接口,當(dāng)你需要對一個已有的類的數(shù)組或者集合進行比較的時候就一定要實現(xiàn)Comparator接口。另外,這兩個接口是支持泛型的,所以我們應(yīng)該在實現(xiàn)接口的同時定義比較類型。

  Java中HashMap的工作原理是?

  Java中的HashMap是以鍵值對(key-value)的形式存儲元素的。HashMap需要一個hash函數(shù),它使用hashCode()和equals()方法來向集合/從集合添加和檢索元素。當(dāng)調(diào)用put()方法的時候,HashMap會計算key的hash值,然后把鍵值對存儲在集合中合適的索引上。如果key已經(jīng)存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負(fù)載因子(load factor)和擴容極限(threshold resizing)。

  1)HashMap有一個叫做Entry的內(nèi)部類,它用來存儲key-value對。

  2)上面的Entry對象是存儲在一個叫做table的Entry數(shù)組中。

  3)table的索引在邏輯上叫做“桶”(bucket),它存儲了鏈表的第一個元素。

  4)key的hashcode()方法用來找到Entry對象所在的桶。

  5)如果兩個key有相同的hash值,他們會被放在table數(shù)組的同一個桶里面。

  6)key的equals()方法用來確保key的唯一性。

  7)value對象的equals()和hashcode()方法根本一點用也沒有。

  重點內(nèi)容

  Put:根據(jù)key的hashcode()方法計算出來的hash值來決定key在Entry數(shù)組的索引。

  Get:通過hashcode找到數(shù)組中的某一個元素Entry

  Hashcode的實現(xiàn)

  hashCode 的常規(guī)協(xié)定是:

  在 Java 應(yīng)用程序執(zhí)行期間,在同一對象上多次調(diào)用 hashCode 方法時,必須一致地返回相同的整數(shù),前提是對象上 equals 比較中所用的信息沒有被修改。從某一應(yīng)用程序的一次執(zhí)行到同一應(yīng)用程序的另一次執(zhí)行,該整數(shù)無需保持一致。

  如果根據(jù) equals(Object) 方法,兩個對象是相等的,那么在兩個對象中的每個對象上調(diào)用 hashCode 方法都必須生成相同的整數(shù)結(jié)果。

  當(dāng)equals方法被重寫時,通常有必要重寫 hashCode 方法,以維護 hashCode 方法的常規(guī)協(xié)定,該協(xié)定聲明相等對象必須具有相等的哈希碼。

  String、StringBffer、StringBuilder的區(qū)別

  1)可變與不可變

  String類中使用字符數(shù)組保存字符串,如下就是,因為有“final”修飾符,所以可以知道string對象是不可變的。

  private final char value[];

  StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數(shù)組保存字符串,如下就是,可知這兩種對象都是可變的。

  char[] value;

  2)是否多線程安全

  String中的對象是不可變的,也就可以理解為常量,顯然線程安全。

  AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

  StringBuffer對方法加了同步鎖或者對調(diào)用的方法加了同步鎖,所以是線程安全的

3152971