JavaRush /Java Blog /Random-KO /상위 50개 Java Core 인터뷰 질문 및 답변. 2 부
Roman Beekeeper
레벨 35

상위 50개 Java Core 인터뷰 질문 및 답변. 2 부

Random-KO 그룹에 게시되었습니다
상위 50개 Java Core 인터뷰 질문 및 답변. 1 부 상위 50개 Java Core 인터뷰 질문 및 답변.  파트 2 - 1

컬렉션

25. Java에서 컬렉션이란 무엇을 의미합니까?

컬렉션은 객체를 저장하고 조작하도록 설계된 프레임워크입니다. 다음 작업을 수행하는 데 사용됩니다.
  • 찾다;
  • 정렬;
  • 시장 조작;
  • 덧셈;
  • 삭제.
컬렉션 프레임워크의 모든 클래스와 인터페이스가 java.util패키지에 있습니다.

26. 컬렉션 프레임워크에서는 어떤 클래스와 인터페이스를 사용할 수 있습니까?

인터페이스:
  • 수집;
  • 목록;
  • 세트;
  • 지도;
  • 정렬된 집합;
  • 정렬된 지도;
  • 대기줄.
클래스:
  • 기울기:
    1. 배열목록;
    2. 링크드리스트;
    3. 벡터(더 이상 사용되지 않음).
  • 세트:
    1. 해시세트;
    2. LinkedHashSet;
    3. 트리세트.
  • 지도:
    1. 해시맵
    2. 트리맵
    3. HashTable(더 이상 사용되지 않음)
    4. LinkedHashMap
  • 대기줄
    1. 우선순위 대기열.

27. 컬렉션에서 정렬 및 정렬된다는 것은 무엇을 의미합니까?

주문한 것:

즉, 컬렉션에 추가된 값을 기준으로 컬렉션에 저장되는 항목이 결정됩니다. 이렇게 하면 특정 순서로 컬렉션의 값을 반복할 수 있습니다. 즉, 이는 컬렉션의 요소가 배열된 고유한 특정 순서를 가지고 있음을 의미합니다. 더 나은 이해를 위해 순서가 지정되지 않은 컬렉션은 해당 요소를 임의의 순서로 저장합니다. 예를 들어 설정합니다.

정렬됨:

이는 요소 그룹이 컬렉션 요소의 데이터를 기반으로 컬렉션으로 정렬됨을 의미합니다. 즉, 컬렉션의 순서가 지정될 뿐만 아니라 요소의 순서도 해당 값에 따라 달라집니다. 다른 요소 값을 기준으로 정렬하면 이 순서가 변경될 수 있습니다.

28. 목록 인터페이스에는 어떤 컬렉션이 있습니까? 리스트 작업은 어떻게 하나요?

시트의 요소 값은 색인을 기반으로 하며 색인별로 정렬됩니다. 요소의 반복이 허용됩니다. 즉, 동일한 개체를 컬렉션에 여러 번 추가해도 괜찮습니다.

배열목록:

가장 일반적인 컬렉션입니다. 기본적으로 크기가 동적으로 확장되는 배열입니다. 배열의 크기를 관리하는 작업은 컬렉션에 있습니다. 대부분의 경우 이것이 우리가 사용해야 하는 것임을 이해하는 것이 중요합니다. 특징:
  • 빠른 검색 및 빠른 색인 검색;
  • 컬렉션은 인덱스별로 정렬되지만 정렬되지는 않습니다.
  • RandomAccess 인터페이스를 구현합니다.
  • 천천히 목록 중간에 추가됩니다.
예:
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 Core 인터뷰 질문 및 답변.  파트 2 - 2
  • 요소는 서로 연결되어 있습니다. 즉, 이중 연결 목록이 구현됩니다.
  • 전체 작업 속도는 ArrayList보다 눈에 띄게 느립니다.
  • 배열 중간에 많은 수의 삽입 및 삭제를 수행하는 데 탁월한 선택입니다.
  • Queue 및 Deque 목록 인터페이스를 구현하므로 작업 방법이 있습니다.
예:
LinkedList<String> linkedList = new LinkedList<>();
linkedList.add("One");
linkedList.add("Two");
linkedList.add("Three");

29. 지도 컬렉션과 그 구현에 대해 알려주십시오.

맵은 키-값 컬렉션입니다. 고유한 키와 해당 값과 일치하는 값이 있습니다. 키의 고유성을 결정하는 데 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" 요소가 단일 인스턴스에만 존재하는 것을 볼 수 있습니다. 그리고 순서는 추가할 때와 동일하지 않습니다.

LinkedHashSet:

  • 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 Core 인터뷰 질문 및 답변.  파트 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 및 throw는 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. 자바에서 던지고 던지기

던지다

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에는 체크된 예외와 체크되지 않은 예외의 두 가지 유형이 있습니다.

확인된 예외:

이는 컴파일 타임에 확인되는 예외입니다. 메소드의 일부 코드가 예외 중에 확인된 예외를 발생시키는 경우 메소드는 를 사용하여 이를 처리 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);
   }
}
이러한 코드는 컴파일되지 않습니다. 왜냐하면 정적 메소드가 IOException을 ImageIO.read()발생시키므로 ImageIO.write()이를 확인하고 이에 따라 처리해야 하기 때문입니다. 위에서 이미 논의한 두 가지 옵션이 있습니다. 사용 try-catch또는 추가 전달입니다. 더 나은 동화를 위해 우리는 이것저것을 할 것입니다. 즉, updateAndSave메소드에서 전달한 다음 기본 메소드에서 사용합니다 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 Core 인터뷰 질문 및 답변.  파트 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 아카이브의 압축이 풀립니다. 이렇게 하려면 'om'을 사용해야 합니다 InputStream. 둘 이상의 변수를 정의할 수 있으며 변수는 세미콜론으로 구분됩니다. 뭐가 문제 야? finally하지만 블록을 사용할 수 있다고 말할 수도 있습니다. 이 접근 방식의 문제점을 자세히 설명하는 기사는 다음과 같습니다 . 또한 이 디자인을 사용하지 않는 사람에게 발생할 수 있는 전체 실패 목록도 설명합니다. 읽어보시길 권합니다 ;) 마지막 부분 에는 멀티스레딩 주제에 대한 질문/답변이 있습니다. 내 GitHub 프로필
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION