JavaRush /Java Blog /Random-TW /Java 開發者訪談問答分析。第15部分

Java 開發者訪談問答分析。第15部分

在 Random-TW 群組發布
嗨嗨!Java 開發人員需要了解多少知識?你可以在這個問題上爭論很長時間,但事實是,在面試中你將被理論所驅使。即使在那些您將沒有機會在工作中使用的知識領域。 Java 開發者訪談問答分析。 第 15 - 1 部分好吧,如果你是初學者,你的理論知識將會受到非常重視。由於還沒有經驗和偉大的成就,剩下的就是檢查知識庫的強度。今天,我們將透過研究 Java 開發人員最流行的面試問題來繼續加強這一基礎。讓我們飛!

Java核心

9. Java中靜態綁定和動態綁定有什麼差別?

這個問題我在第18題關於靜態多態和動態多態的這篇文章中已經回答過,建議你閱讀。

10. 是否可以在介面中使用私有或受保護的變數?

你不能。因為當你宣告一個介面時,Java編譯器會自動在介面方法之前加入publicabstract關鍵字,在資料成員之前加入publicstaticfinal關鍵字。實際上,如果加入privateprotected,就會產生衝突,編譯器會抱怨存取修飾符,並顯示以下訊息:「Modifier '<selected modifier>' not allowed here.」為什麼編譯器要加入publicstaticFinal介面中的變數?我們來算一下:
  • public - 介面允許客戶端與物件互動。如果變數不是公開的,客戶端將無法存取它們。
  • static - 無法建立介面(或更確切地說,它們的物件),因此變數是靜態的。
  • Final - 由於該介面用於實現 100% 抽象,因此該變數具有其最終形式(並且不會更改)。

11.什麼是類別載入器以及它的用途是什麼?

類別載入器- 或類別載入器 - 提供 Java 類別的載入。更準確地說,載入是由其後代(特定的類別載入器)確保的,因為 ClassLoader本身是抽象的。每次載入 .class 檔案時,例如,在呼叫對應類別的建構子或靜態方法之後,此操作都會由ClassLoader類別的後代之一執行。繼承人分為三種類型:
  1. Bootstrap ClassLoader是一個基本的載入器,在 JVM 層級實現,沒有來自執行時間環境的回饋,因為它是 JVM 核心的一部分並用本機程式碼編寫。此載入器充當所有其他 ClassLoader 實例的父級。

    主要負責載入JDK內部類,通常是位於$JAVA_HOME/jre/lib目錄下的rt.jar等核心庫。不同的平台可能對該類別載入器有不同的實作。

  2. 擴充類別載入器是一個擴充載入器,是基本載入器類別的後代。負責載入標準 Java 基底類別的擴充。從 JDK 擴充目錄加載,通常是$JAVA_HOME/lib/ext或 java.ext.dirs 系統屬性中提到的任何其他目錄(此選項可用於控制擴充功能的載入)。

  3. System ClassLoader是在 JRE 層級實作的系統載入器,負責將所有應用程式層級的類別載入到 JVM 中。它載入在類別環境變數-classpath-cp命令列選項中找到的檔案。

Java 開發者訪談問答分析。 第 15 - 2 部分類別載入器是 Java 運行時的一部分。當 JVM 請求一個類別時,類別載入器會嘗試尋找該類別並使用該類別的完全限定名稱將類別定義載入到執行時。java.lang.ClassLoader.loadClass()方法負責在執行時期載入類別定義。它嘗試根據類別的全名載入類別。如果該類別尚未加載,它將請求委託給父類別載入器。此過程遞歸發生,如下所示:
  1. 系統類別載入器嘗試在其快取中尋找該類別。

    • 1.1. 如果找到該類,則載入成功完成。

    • 1.2. 如果未找到該類,則將載入委託給擴充類別載入器。

  2. 擴充類別載入器嘗試在自己的快取中尋找該類別。

    • 2.1. 如果找到該類,則它成功完成。

    • 2.2. 如果未找到該類,則將載入委託給引導類別載入器。

  3. Bootstrap 類別載入器嘗試在自己的快取中尋找該類別。

    • 3.1. 如果找到該類,則載入成功完成。

    • 3.2. 如果找不到該類,底層的 Bootstrap 類載入器將嘗試載入它。

  4. 如果加載:

    • 4.1. 成功 - 類別載入完成。

    • 4.2. 如果失敗,控制權將轉移到擴充類別載入器。

  5. 5.擴充類載入器嘗試載入類,如果載入:

    • 5.1. 成功 - 類別載入完成。

    • 5.2. 如果不成功,控制權將轉移到系統類別載入器。

  6. 6.系統類載入器嘗試載入類,如果載入:

    • 6.1. 成功 - 類別載入完成。

    • 6.2. 沒有成功通過——產生異常——ClassNotFoundException。

類別載入器這個話題涉及面很廣,不應該被忽視。為了更詳細地了解它,我建議您閱讀這篇文章,我們不會徘徊並繼續前進。

12. 什麼是運行時資料區?

Run-Time Data Ares - JVM 執行時期資料區域。JVM定義了程式執行過程中所需的一些執行時間資料區域。其中一些是在 JVM 啟動時創建的。其他的是線程本地的,僅在創建線程時創建(並在線程銷毀時銷毀)。JVM 運行時資料區域如下所示: Java 開發者訪談問答分析。 第 15 - 3 部分
  • PC暫存器是每個執行緒本地的,包含執行緒目前正在執行的JVM指令的位址。

  • JVM 堆疊是一個記憶體區域,用於儲存局部變數和暫存結果。每個執行緒都有自己獨立的堆疊:一旦執行緒終止,該堆疊也會被銷毀。值得注意的是,棧相對於堆的優勢在於效能,而堆在儲存規模上當然更有優勢。

  • 本機方法堆疊 - 儲存資料元素的每個執行緒資料區域,類似於 JVM 堆疊,用於執行本機(非 Java)方法。

  • 堆 - 被所有執行緒用作存儲,其中包含在運行時創建的物件、類元資料、數組等。該區域在 JVM 啟動時創建,在 JVM 關閉時銷毀。

  • 方法區 - 該運行時區域對所有執行緒都是公共的,並且在 JVM 啟動時建立。它儲存每個類別的結構,例如運行時常數池、建構函數和方法的程式碼、方法資料等。

13.什麼是不可變對象?

文章這一部分,第14題和第15題中,已經有這個問題的答案了,看一下,別浪費時間了。

14. String類別有什麼特別之處?

在前面的分析中,我們反覆討論了String 的某些特性(對此有一個單獨的部分)。現在讓我們來總結一下String的特色:
  1. 它是 Java 中最受歡迎的對象,有多種用途。從使用頻率上來說,甚至不遜於原始類型。

  2. 無需使用 new 關鍵字即可建立此類別的物件 - 直接透過引號String str = “string”;

  3. String一個不可變的類別:當建立該類別的物件時,它的資料不能改變(當你在某個字串上新增+「另一個字串」時,結果你將得到一個新的第三個字串)。String 類別的不變性使其成為線程安全的。

  4. String類別是finalized的(有final修飾符),所以不能被繼承。

  5. String有自己的字串池,它是堆中的一塊記憶體區域,用於快取它創建的字串值。在本系列的這一部分中,在問題 62 中,我描述了字串池。

  6. Java 有String 的類似物,也設計用於處理字串 - StringBuilderStringBuffer,但不同之處在於它們是可變的。您可以在本文中閱讀有關它們的更多資訊。

Java 開發者訪談問答分析。 第 15 - 4 部分

15.什麼是類型協方差?

為了理解協方差,我們將看一個例子。假設我們有一個動物類:
public class Animal {
 void voice() {
   System.out.println("*тишина*");
 }
}
還有一些Dog類擴展它:
public class Dog extends Animal {

 @Override
 public void voice() {
   System.out.println("Гав, гав, гав!!!");
 }
}
我們記得,我們​​可以輕鬆地將繼承類型的物件指派給父類型:
Animal animal = new Dog();
這只不過是多態性。是不是方便、靈活?那麼,動物名單呢?我們可以給出一個包含通用Animal 的列表和包含Dog物件的列表嗎?
List<Dog> dogs = new ArrayList<>();
List<Animal> animals = dogs;
在這種情況下,將狗清單分配給動物清單的行將以紅色下劃線顯示,即 編譯器不會通過此程式碼。儘管這個賦值看起來很合乎邏輯(畢竟,我們可以將Dog物件賦值給Animal類型的變數),但它無法完成。這是因為如果允許的話,我們將能夠將Animal物件放入原本打算成為Dog 的清單中,同時認為清單中只有Dogs。然後,例如,我們將使用get()方法從列表中獲取一個對象,認為它是一隻狗,並在其上調用Dog對象的某些方法,這是Animal沒有的。正如您所理解的,這是不可能的 - 將會發生錯誤。但是,幸運的是,編譯器不會錯過將後代列表分配給父級列表的邏輯錯誤(反之亦然)。在 Java 中,您只能將列表物件指派給具有匹配泛型的列表變數。這稱為不變性。如果他們能做到這一點,那就被稱為協方差。也就是說,協方差是指我們是否可以將ArrayList<Dog>類型的物件設定為List<Animal>類型的變數。原來Java中不支援協方差?不管怎麼樣! 但這是以它自己特殊的方式完成的。設計是用來做什麼的擴充了 Animal。它與我們想要設定列表物件的變數的泛型以及後代的泛型一起放置。這種通用構造意味著任何Animal類型的後代類型都可以(並且Animal類型也屬於這種概括)。反過來,Animal不僅可以是一個類,還可以是一個介面(不要被extends關鍵字迷惑)。我們可以像這樣完成之前的任務: Java 開發者訪談問答分析。 第 15 - 5 部分
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
因此,您將在 IDE 中看到編譯器不會抱怨此構造。讓我們檢查一下這個設計的功能。假設我們有一個方法,可以讓傳遞給它的所有動物發出聲音:
public static void animalsVoice(List<? extends Animal> animals) {
 for (Animal animal : animals) {
   animal.voice();
 }
}
讓我們給他一份狗的清單:
List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
dogs.add(new Dog());
animalsVoice(dogs);
在控制台中我們將看到以下輸出:
汪汪汪!!!汪汪汪!!!汪汪汪!!!
這意味著這種協方差方法是成功的。讓我注意一下,這個通用名包含在清單中?擴充 Animal我們不能插入任何類型的新資料:既不能插入Dog類型,也不能插入Animal類型:
List<Dog> dogs = new ArrayList<>();
List<? extends Animal> animals = dogs;
animals.add(new Dog());
dogs.add(new Animal());
實際上,在最後兩行中,編譯器將以紅色突出顯示物件的插入。這是因為我們無法百分之百確定哪個類型的物件清單將透過通用<? 擴展動物>Java 開發者訪談問答分析。 第 15 - 6 部分我還想談談逆變,因為通常這個概念總是與協變聯繫在一起,通常他們會一起被問到。這個概念在某種程度上與協方差相反,因為該構造使用繼承人類型。假設我們想要一個列表,該列表可以分配不是Dog物件祖先的類型物件列表。然而,我們事先並不知道它們具體是什麼類型。在這種情況下,形式的構造?super Dog,所有類型都適合 - Dog類的祖先:
List<Animal> animals = new ArrayList<>();
List<? super Dog> dogs = animals;
dogs.add(new Dog());
dogs.add(new Dog());
我們可以使用這樣的泛型安全地將Dog類型的物件新增到列表中,因為在任何情況下它都具有其任何祖先的所有實作方法。但是我們將無法新增Animal類型的對象,因為無法確定內部是否存在該類型的對象,而不是Dog等類型的對象。畢竟,我們可以從此清單的元素請求Dog類別的方法,而Animal則沒有。在這種情況下,會出現編譯錯誤。另外,如果我們想實作前面的方法,但使用這個泛型:
public static void animalsVoice(List<? super Dog> dogs) {
 for (Dog dog : dogs) {
   dog.voice();
 }
}
我們會在for迴圈 中遇到編譯錯誤,因為我們無法確定傳回的清單包含Dog類型的物件並且可以自由使用其方法。如果我們呼叫這個列表上的dogs.get(0)方法。- 我們將得到一個Object 類型的物件。也就是說,為了讓AnimalsVoice()方法運作,我們至少需要增加一些小的運算來縮小型別資料:
public static void animalsVoice(List<? super Dog> dogs) {
 for (Object obj : dogs) {
   if (obj instanceof Dog) {
     Dog dog = (Dog) obj;
     dog.voice();
   }
 }
}
Java 開發者訪談問答分析。 第 15 - 7 部分

16.Object類別中有哪些方法?

系列的第 11 段中,我已經回答了這個問題,因此,如果您還沒有這樣做,我強烈建議您閱讀它。今天我們就到此結束。下一部分見! Java 開發者訪談問答分析。 第 15 - 8 部分
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION