상위 50개 Java Core 인터뷰 질문 및 답변. 1 부
컬렉션
25. Java에서 컬렉션이란 무엇을 의미합니까?
컬렉션은 객체를 저장하고 조작하도록 설계된 프레임워크입니다. 다음 작업을 수행하는 데 사용됩니다.- 찾다;
- 정렬;
- 시장 조작;
- 덧셈;
- 삭제.
java.util
패키지에 있습니다.
26. 컬렉션 프레임워크에서는 어떤 클래스와 인터페이스를 사용할 수 있습니까?
인터페이스:- 수집;
- 목록;
- 세트;
- 지도;
- 정렬된 집합;
- 정렬된 지도;
- 대기줄.
- 기울기:
- 배열목록;
- 링크드리스트;
- 벡터(더 이상 사용되지 않음).
- 세트:
- 해시세트;
- LinkedHashSet;
- 트리세트.
- 지도:
- 해시맵
- 트리맵
- HashTable(더 이상 사용되지 않음)
- LinkedHashMap
- 대기줄
- 우선순위 대기열.
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를 종료할 필요도 없습니다.
연결 목록:
이는 각 요소가 이전 요소와 다음 요소에 대한 링크를 갖는 컬렉션입니다. 이러한 링크를 사용하면 한 요소에서 다른 요소로 이동할 수 있습니다. 요소를 추가하면 이전 요소와 다음 요소에 대한 링크가 변경됩니다.- 요소는 서로 연결되어 있습니다. 즉, 이중 연결 목록이 구현됩니다.
- 전체 작업 속도는 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}
트리맵:
키의 자연스러운 순서에 따라 항목을 정렬하는 맵 구현입니다. 또는 맵이 생성될 때 생성자에 비교기가 제공되는 경우 비교기를 사용하는 것이 더 좋습니다. 예:-
비교기 없음
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}
-
비교기 있음
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}
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. 예외란 무엇입니까?
예외는 런타임 시 발생할 수 있는 문제입니다. 이는 어떤 이유로 발생하는 예외적인 상황입니다. 예외 상속 다이어그램은 다음과 같습니다(암기해야 합니다. ;)). 이 다이어그램은 일반적으로 모든 예외가 예외 와 오류라는 두 그룹으로 나누어져 있음을 보여줍니다. 오류 - 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. 프로그래머는 예외를 어떻게 처리합니까?
위의 질문에서 우리는 이미 특정 키워드를 사용하여 예외 작업을 수행했습니다. 이제 이에 대해 더 자세히 이야기해야 합니다. 키워드는 무엇입니까?- 노력하다
- 잡다
- 던지다
- 던진다
- 마지막으로
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
있지만 매너는 그렇지 않다고 말합니다. 이것이 체크 가능한 것이라면, 이를 생성하는 메소드를 사용하여 어떻게든 처리해야 합니다. 두 가지 옵션이 있습니다:
try-catch
적절한 상속 예외를 사용하여 작성합니다 .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가 선택 해제되어 있습니다. 다음 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 프로필
GO TO FULL VERSION