JavaRush /Java Blog /Random-TW /前 50 個 Java 核心面試問題和答案。第2部分
Roman Beekeeper
等級 35

前 50 個 Java 核心面試問題和答案。第2部分

在 Random-TW 群組發布
前 50 個 Java 核心面試問題和答案。第1部分 前 50 個 Java 核心面試問題和答案。 第 2 - 1 部分

收藏

25. Java中集合是什麼意思?

集合是一個旨在儲存和操作物件的框架。用於執行以下操作:
  • 搜尋;
  • 排序;
  • 操縱;
  • 添加;
  • 刪除。
Collection 框架的所有類別和介面都在java.util套件中。

26. Collection框架中有哪些類別和介面可用?

接口:
  • 收藏;
  • 列表;
  • 放;
  • 地圖;
  • 排序集;
  • 排序地圖;
  • 隊列。
課程:
  • 列表:
    1. 數組列表;
    2. 鍊錶;
    3. 向量(已棄用)。
  • 套:
    1. 哈希集;
    2. 鏈接哈希集;
    3. 樹集。
  • 地圖:
    1. 哈希映射
    2. 樹狀圖
    3. 哈希表(已棄用)
    4. 連結哈希映射
  • 佇列
    1. 優先隊列。

27.集合中排序和排序是什麼意思?

訂購:

這意味著儲存在集合中的項目是基於添加到集合中的值。這樣我們就可以按照特定的順序迭代集合中的值。換句話說,這意味著集合的元素有自己特定的排列順序。為了更好地理解,未排序的集合以隨機順序儲存其元素。例如,設定。

排序:

這意味著根據集合元素的資料將一組元素排序到集合中。也就是說,不僅集合是有序的,而且元素的順序也取決於它們的值。如果您按不同的元素值排序,則此順序可能會變更。

28. 有哪些集合具有List介面?你如何與清單一起工作?

工作表中元素的值是基於它們的索引——它們按索引排序。元素重複是允許的(也就是說,你可以多次將同一個物件加入集合就可以了)。

數組列表:

最常見的集合。本質上,它是一個大小動態擴展的陣列。管理數組大小的工作由集合負責。對我們來說,重要的是要了解,在大多數情況下,這就是我們需要使用的。特點:
  • 快速搜尋和快速索引搜尋;
  • 集合按索引排序,但未排序;
  • 實現隨機存取介面;
  • 慢慢地添加到清單的中間。
例子:
public class A {

   public static void main(String[] args) {
       ArrayList names = new ArrayList<>();
       names.add("John");
       names.add("John");
       names.add("Roman");
       names.add("Ivan");
   }

}
>> 輸出

   [John, John, Roman, Ivan]
輸出顯示這些是可重複的元素。它們按照記錄的順序顯示。還有什麼可讀的?是的,有很多訊息,你甚至不需要離開 JavaRush:

連結列表:

這是一個集合,其中每個元素都有到上一個和下一個元素的連結。這些連結允許您從一個元素移動到另一個元素。當添加元素時,前一個和下一個元素的連結只會改變: 前 50 個 Java 核心面試問題和答案。 第 2 - 2 部分
  • 元素之間相互連接,即實現了雙向鍊錶;
  • 整體運行速度明顯低於ArrayList;
  • 對於在數組中間進行大量插入和刪除的絕佳選擇;
  • 實作了 Queue 和 Deque 列表接口,因此有它們的工作方法。
例子:
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");

29. 請介紹 Map 集合及其實作?

Map 是一個鍵值集合。有一個唯一的鍵和一個與該值相符的值。equals()方法也用於hashcode()確定密鑰的唯一性。

哈希映射:

  • 未分類或排序;
  • 如果順序和排序不重要則使用;
  • 支援空鍵。
例子:
public class CollectionExample {

   public static void main(String[] args) {
       HashMap positions = new HashMap<>();
       positions.put("junior", "Ivan");
       positions.put("middle", "Roman");
       positions.put("senior", "Vasily");
       positions.put("team lead", "Anton");
       positions.put("arthitect", "Andrew");
       positions.put("senior", "John");
       System.out.println(positions);
   }
}

// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}
密鑰始終是唯一的,因此只記錄了一位高級人員。

連結哈希映射:

  • 維護插入順序;
  • 比HashMap慢;
  • 迭代預計比 HashMap 更快。
例子:
public class CollectionExample {

   public static void main(String[] args) {
       LinkedHashMap<String, String> positions = new LinkedHashMap<>();
       positions.put("junior", "Ivan");
       positions.put("middle", "Roman");
       positions.put("senior", "Vasily");
       positions.put("team lead", "Anton");
       positions.put("arthitect", "Andrew");
       positions.put("senior", "John");
       System.out.println(positions);
   }
}

// вывод в консоль
// {junior=Ivan, middle=Roman, senior=John, team lead=Anton, arthitect=Andrew}

樹狀圖:

一種映射實現,可以根據鍵的自然順序對條目進行排序,或者更好的是,如果在建立映射時在構造函數中提供了比較器,則使用比較器。例子:
  1. 不含比較器

    public class CollectionExample {
    
       public static void main(String[] args) {
           TreeMap<Integer, String> positions = new TreeMap<>();
           positions.put(1, "Ivan");
           positions.put(3, "Roman");
           positions.put(2, "Vasily");
           positions.put(10, "Anton");
           positions.put(7, "Andrew");
           positions.put(1, "John");
           System.out.println(positions);
       }
    }
    
    // вывод в консоль
    // {1=John, 2=Vasily, 3=Roman, 7=Andrew, 10=Anton}
  2. 附比較器

    public class CollectionExample {
    
       public static void main(String[] args) {
           //используем реализацию Strategy Pattern'a и добавим компаратор:
           TreeMap<Integer, String> positions = new TreeMap<>(Comparator.reverseOrder());
           positions.put(1, "Ivan");
           positions.put(3, "Roman");
           positions.put(2, "Vasily");
           positions.put(10, "Anton");
           positions.put(7, "Andrew");
           positions.put(1, "John");
           System.out.println(positions);
       }
    }
    
    // вывод в консоль
    // {10=Anton, 7=Andrew, 3=Roman, 2=Vasily, 1=John}
我們看到按升序排序是作為標準實現的,但是可以透過向建構函數添加比較器來更改這一點。TreeMap在這裡得到了很好的描述。

30. 給我們介紹一下Set集合及其實作?

集合是唯一元素的集合,這是它的主要特徵。即Set不允許相同的元素重複出現。 這裡重要的是,新增的物件必須實作一個方法 equals

哈希集:

  • 未排序或排序。在底層有一個帶有值佔位符的 HashMap。你自己看 ;)
  • 使用hashCode添加物件;
  • 當您需要擁有唯一的物件並且它們的順序並不重要時,應該使用它。
例子:
public class CollectionExample {

   public static void main(String[] args) {
       HashSet<String> positions = new HashSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [senior, middle, team lead, architect, junior]
在這裡您可以看到新增了兩次的「junior」元素僅出現在一個實例中。而且順序和添加時不一樣。

連結哈希集:

  • HashSet 的有序版本;
  • 支援所有元素的雙向鍊錶;
  • 當迭代過程中需要有序性時使用它。
例子:
public class CollectionExample {

   public static void main(String[] args) {
       LinkedHashSet<String> positions = new LinkedHashSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [senior, middle, team lead, architect, junior]

樹集:

  • 兩個已排序集合之一;
  • 採用紅黑樹結構,並保證元素依升序排列;
  • 在底層,它是一個帶有值存根的 TreeMap。TreeSet 的元素是 TreeMap 的鍵(另請參閱;))。
例子:
public class CollectionExample {

   public static void main(String[] args) {
       TreeSet<String> positions = new TreeSet<>();
       positions.add("junior");
       positions.add("junior");
       positions.add("middle");
       positions.add("senior");
       positions.add("team lead");
       positions.add("architect");
       System.out.println(positions);
   }
}

// вывод в консоль
// [architect, junior, middle, senior, team lead]

例外情況

31.什麼是異常?

異常是運行時可能發生的問題。這是由於某種原因而出現的特殊情況。異常繼承圖如下所示(您需要熟記在心;)): 前 50 個 Java 核心面試問題和答案。 第 2 - 3 部分此圖顯示,一般來說,所有異常都分為兩組 -異常錯誤。 錯誤- JVM 用於顯示錯誤,之後應用程式不再有意義。例如,StackOverFlowError,它表示堆疊已滿,程式無法再運行。 異常- 在程式碼中以程式設計方式產生的異常。有各種異常,檢查的和未檢查的,但最重要的是它們存在,並且可以捕獲它們並且應用程式可以繼續運行。異常又進一步分為繼承自 RuntimeException 的異常和 Exception 的其他後代。關於這個問題有足夠的資訊。我們將在下面討論什麼是檢查/非檢查異常。

32. JVM如何處理異常?

怎麼運作的?一旦某個地方拋出異常,運行時就會建立一個異常物件(表示為 ExcObj)。它儲存工作所需的所有資訊 - 引發的異常本身以及發生的位置。創建ExcObj並傳輸到運行時無非就是“拋出異常”。 ExcObj包含可用於到達引發異常的位置的方法。這組方法稱為呼叫堆疊。接下來,運行時系統在呼叫堆疊中尋找可以處理異常的方法。如果它確實找到了對應的處理程序,即異常類型與處理程序中的類型匹配,則一切正常。如果找不到,運行時會將所有內容傳遞給預設異常處理程序,該處理程序準備回應並退出。視覺上看起來如何:
/**
* Пример, в котором показываются две опции — когда находится обработчик для исключения и когда нет.
*/
class ThrowerExceptionExample {

   public static void main(String[] args) throws IllegalAccessException {

       ThrowerExceptionExample example = new ThrowerExceptionExample();

       System.out.println(example.populateString());
   }

   /**
    * Здесь происходит перехват одного из возможных исключений — {@link IOException}.
    * А вот второй будет пробрасываться дальше вверх по вызову.
    */
   private String populateString() throws IllegalAccessException {
       try {
           return randomThrower();
       } catch (IOException e) {
           return "Caught IOException";
       }
   }

   /**
    * Здесь две опции: or бросается {@link IOException} or {@link IllegalAccessException}.
    * Выбирается случайным образом.
    */
   private String randomThrower() throws IOException, IllegalAccessException {
       if (new Random().nextBoolean()) {
           throw new IOException();
       } else {
           throw new IllegalAccessException();
       }
   }
}
在我們的範例中,CallStack 大致如下所示:

randomThrower() => populateString() => main(String[] args)
有兩種選擇:隨機拋出一個或另一個異常。對於 IOException 一切正常,如果產生它,那麼工作結果將是:"Caught IOException"。但是,如果出現第二個沒有處理程序的異常,程式將停止並顯示以下輸出:

Exception in thread "main" java.lang.IllegalAccessException
  at ThrowerExceptionExample.randomThrower(CollectionExample.java:38)
  at ThrowerExceptionExample.populateString(CollectionExample.java:24)
  at ThrowerExceptionExample.main(CollectionExample.java:15)

33. 程式設計師如何處理異常?

在上面的問題中,某些關鍵字已經用於處理異常;現在我們需要更詳細地討論它們。關鍵字是什麼?
  • 嘗試
  • 抓住
  • 投擲
  • 最後
需要注意的是,catch、throw 和 throws 只能與 java.lang.Throwable 一起使用。這不適用於其他類型。現在我們將討論 try、catch 和finally。
  • try-catch-finally是一個允許您正確捕獲和處理異常的構造。
  • try- 只能有一次,即邏輯發生的時刻;
  • catch— 接收某種類型異常的區塊;可以有很多異常。例如,一個try區塊會拋出幾個彼此無關的例外;
  • finally- 「終於」這個區塊。這是一個在任何情況下都會執行的區塊,無論 try、catch 中做了什麼。
它看起來是這樣的:
try {
   // сюда передают тот code, который может вызвать исключение.
} catch (IOException e) {
   // первый catch блок, который принимает IOException и все его подтипы(потомки).
   // Например, нет file при чтении, выпадает FileNotFoundException, и мы уже соответствующе
   // обрабатываем это.
} catch (IllegalAccessException e) {
   // если нужно, можно добавить больше одного catch блока, в этом нет проблем.
} catch (OneException | TwoException e) {
   // можно даже объединять несколько в один блок
} catch (Throwable t) {
   // а можно сказать, что мы принимаем ВСЁ))))
} finally {
   // этот блок может быть, а может и не быть.
   // и он точно выполнится.
}
仔細閱讀例子的描述一切就清楚了)

34. Java 中的 throw 和 throws

throw當您需要明確建立新異常時使用。它用於創建和引發自訂異常。例如,與驗證相關的異常。通常,為了驗證,它們繼承自RuntimeException. 例子:
// пример пробрасывания исключения
throw new RuntimeException("because I can :D");
重要的是,此構造只能由繼承自 的物件使用Throwable。也就是說,你不能這樣說:
throw new String("How тебе такое, Илон Маск?");
接下來,執行緒的工作被終止,並開始搜尋可以處理它的處理程序。當它找不到它時,它會轉到呼叫它的方法,因此搜尋將沿著呼叫行向上進行,直到找到相應的處理程序或讓應用程式保持運行。我們看看吧:
// Пример, который демонстрирует работу throw
class ThrowExample {

   void willThrow() throws IOException {
       throw new IOException("Because I Can!");
   }

   void doSomething() {
       System.out.println("Doing something");
       try {
           willThrow();
       } catch (IOException e) {
           System.out.println("IOException was successfully handled.");
       }
   }

   public static void main(String args[]) {
       ThrowExample throwExample = new ThrowExample();
       throwExample.doSomething();
   }
}
如果我們運行該程序,我們會得到以下結果:

Doing something
IOException was successfully handled.

投擲

throws- 一種方法可以拋出一個或多個異常的機制。它們以逗號分隔添加。讓我們看看它是多麼容易和簡單:
private Object willThrow() throws RuntimeException, IOException, FileNotFoundException
此外,值得注意的是,可以存在受控異常和非受控異常。當然,未經檢查的異常可能不會被添加到 中throws,但出於禮貌,否則會這樣說。如果這些是可檢查的,那麼使用產生它們的方法,您需要以某種方式處理它。有兩種選擇:
  1. try-catch用適當的和上面的繼承異常來寫。
  2. throws以完全相同的方式使用它,以便其他人已經遇到這個問題:D

35. Java中的受檢異常和非受檢異常

Java中有兩種類型的異常—受控異常和非受控異常。

檢查異常:

這些是在編譯時檢查的異常。如果方法中的某些程式碼在異常期間拋出已檢查的異常,則該方法必須使用 處理它try-catch,或進一步轉發它。例如,從路徑“/users/romankh3/image.png”讀取圖像,並更新它以某種方式(對我們來說這並不重要)並將其保存回來。
class CheckedImageExample {
   public static void main(String[] args) {
       File imageFile = new File("/users/romankh3/image.png");
       BufferedImage image = ImageIO.read(imageFile);
       updateAndSaveImage(image, imageFile);
   }

   private static void updateAndSaveImage(BufferedImage image, File imageFile) {
       ImageIO.write(image, "png", imageFile);
   }
}
這類程式碼將無法編譯,因為靜態方法ImageIO.read()會拋出ImageIO.write()IOException,該例外會被檢查並必須進行對應處理。這裡有兩個選項我們已經在上面討論過:要麼使用try-catch,要麼進一步轉發。為了更好地同化,我們會做這做那。也就是說,updateAndSave我們只需在方法中轉發它,然後在 main 方法中使用它try-catch
class CheckedImageExample {
   public static void main(String[] args) {
       File imageFile = new File("/users/romankh3/image.png");
       try {
           BufferedImage image = ImageIO.read(imageFile);
           updateAndSaveImage(image, imageFile);
       } catch (IOException e) {
           e.printStackTrace();
       }
   }

   private static void updateAndSaveImage(BufferedImage image, File imageFile) throws IOException {
       ImageIO.write(image, "png", imageFile);
   }
}

未經檢查的異常:

這些是在編譯階段不檢查的異常。也就是說,一個方法可以產生 RuntimeException,但編譯器不會提醒您以某種方式處理它。如下所示,我們將所有繼承自 RuntimeException 和 Error 的內容都取消選取。 前 50 個 Java 核心面試問題和答案。 第 2 - 4 部分考慮以下 Java 程式。該程式碼編譯良好,但在運行時拋出異常ArrayIndexOutOfBoundsException。編譯器允許它編譯,因為ArrayIndexOutOfBoundsException它是未經檢查的異常。數組的常見情況可能是:
class CheckedImageExample {
   public static void main(String[] args) {
       int[] array = new int[3];
       array[5] = 12;
   }
}
結果將是:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
  at main(CheckedImageExample.java:12)
順便說一句,您是否已經注意到在 Java 中沒有人給出短名稱?越大越好。他,Spring Framework,在這方面非常成功:只需使用一些BeanFactoryPostProcessor類別))))

36. 什麼是資源嘗試?

這是一種必須正確關閉所有資源的機制。有點不清楚,對吧?)首先,什麼是資源…資源是一個對象,使用後需要關閉它,即調用close(). 資源是指實作介面的所有對象AutoClosable,而對象又實作介面Closeable。對我們來說,重要的是要明白一切InputStream都是OutpuStream資源,都需要正確、成功地釋放。這正是我們需要使用try-with-resource該結構的原因。它看起來是這樣的:
private void unzipFile(File zipFile) throws IOException {
   try(ZipInputStream zipOutputStream = new ZipInputStream(new FileInputStream(zipFile))) {
       ZipEntry zipEntry = zipOutputStream.getNextEntry();
       while (zipEntry != null) {

       }
   }
}

private void saveZipEntry(ZipEntry zipEntry) {
   // логика сохранения
}
在此範例中,資源為ZipInputStream,使用後您需要將其關閉。為了不考慮呼叫方法close(),我們只需在 try 區塊中定義此變量,如範例所示,並在該區塊中執行所有必要的操作。這個例子有什麼作用?它將解壓縮 zip 檔案。為此,您需要使用InputStream'om. 您可以定義多個變數;它們之間用分號分隔。有什麼問題?但您finally可能會說,您可以使用區塊。這裡有一篇文章詳細介紹了這種方法的問題。它還描述了忽略使用此設計的人可能遇到的失敗的完整清單。我建議閱讀它;)最後一部分有關於多線程主題的問題/答案。 我的 GitHub 個人資料
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION