Survive-As-a-Developer

Java 8 의 특징들은 무엇이 있나요?
자바 8은 프로그래밍 언어 자바에 많은 혁신을 가져왔습니다. 람다 표현식, 스트림 API, 옵셔널 클래스의 도입은 자바 개발자들이 보다 효율적이고 안정적인 코드를 작성할 수 있게 해주었습니다.

이러한 기능들은 자바의 사용성과 생산성을 크게 향상시켰으며, 함수형 프로그래밍의 도입으로 자바의 패러다임을 확장시켰습니다. 자바 8의 특징들은 현대 소프트웨어 개발에 있어서 중요한 역할을 하고 있습니다.

따라서 자바 개발자라면 자바 8의 주요 특징들을 잘 이해하고 활용할 수 있어야 합니다. 이를 통해 더 나은 소프트웨어 개발을 위한 기반을 마련할 수 있습니다.
  

람다 표현식(Lambda Expressions)

(parameters) -> expression

스트림 API(Stream API)

List<String> filteredList = list.stream().filter(s -> s.startsWith("A")).collect(Collectors.toList());

디폴트 메소드(Default Methods)

interface MyInterface {
   default void newMethod() {
     // default implementation
   }
}

옵셔널 클래스(Optional Class)

Optional<String> optional = Optional.ofNullable(value);

New Date and Time API

LocalDate date = LocalDate.now();


오버로딩(Overloading)과 오버라이딩(Overriding) 대해 설명해보실 수 있나요? </br>
메소드 오버로딩(overloading)이란 
같은 이름의 메소드를 중복하여 정의하는 것을 의미합니다. 자바에서는 원래 한 클래스 내에 같은 이름의 메소드를 둘 이상 가질 수 없습니다. 하지만 매개변수의 개수나 타입을 다르게 하면, 하나의 이름으로 메소드를 작성할 수 있습니다. 즉, 메소드 오버로딩은 서로 다른 시그니처를 갖는 여러 메소드를 같은 이름으로 정의하는 것이라고 할 수 있습니다. 이러한 메소드 오버로딩을 사용함으로써 메소드에 사용되는 이름을 절약할 수 있습니다. 또한, 메소드를 호출할 때 전달해야 할 매개변수의 타입이나 개수에 대해 크게 신경을 쓰지 않고 호출할 수 있게 됩니다. 메소드 오버로딩은 객체 지향 프로그래밍의 특징 중 하나인 다형성(polymorphism)을 구현하는 방법 중 하나입니다. 메소드 오버로딩의 대표적인 예로는 println() 메소드를 들 수 있습니다. println() 메소드는 전달받는 매개변수의 타입에 따라 다음과 같이 다양한 원형 중에서 적절한 원형을 호출하게 됩니다.
1. println() 2. println(boolean x) 3. println(char x) 4. println(char[] x) 5. println(double x) 6. println(float x) 7. println(int x) 8. println(long x) 9. println(Object x) 10. println(String x)
메소드 오버로딩의 조건
자바에서 메소드 오버로딩이 성립하기 위해서는 다음과 같은 조건을 만족해야 합니다. 1. 메소드의 이름이 같아야 합니다. 2. 메소드의 시그니처, 즉 매개변수의 개수 또는 타입이 달라야 합니다. 메소드 오버로딩은 반환 타입과는 관계가 없습니다. 만약 메소드의 시그니처는 같은데 반환 타입만이 다른 경우에는 오버로딩이 성립하지 않습니다.


메소드 오버라이딩(method overriding)
앞서 배운 오버로딩(overloading)이란 서로 다른 시그니처를 갖는 여러 메소드를 하나의 이름으로 정의하는 것이었습니다.

오버라이딩(overriding)이란 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 시그니쳐를 갖는 메소드로 다시 정의하는 것이라고 할 수 있습니다.

자바에서 자식 클래스는 부모 클래스의 private 멤버를 제외한 모든 메소드를 상속받습니다.

이렇게 상속받은 메소드는 그대로 사용해도 되고, 필요한 동작을 위해 재정의하여 사용할 수도 있습니다.

즉, 메소드 오버라이딩이란 상속받은 부모 클래스의 메소드를 재정의하여 사용하는 것을 의미합니다.



오버라이딩의 조건 자바에서 메소드를 오버라이딩하기 위한 조건은 다음과 같습니다. 1. 오버라이딩이란 메소드의 동작만을 재정의하는 것이므로, 메소드의 선언부는 기존 메소드와 완전히 같아야 합니다. 하지만 메소드의 반환 타입은 부모 클래스의 반환 타입으로 타입 변환할 수 있는 타입이라면 변경할 수 있습니다. 2. 부모 클래스의 메소드보다 접근 제어자를 더 좁은 범위로 변경할 수 없습니다 3. 부모 클래스의 메소드보다 더 큰 범위의 예외를 선언할 수 없습니다.
  1. 오버로딩(overloading)은 새로운 메소드를 정의하는 것
  2. 오버라이딩(overriding)은 상속받은 기존의 메소드를 재정의하는 것


GC에 대해서 설명해 볼 수 있나요? </br>
GC 는 JVM에서 메모리를 관리 해주는 모듈 입니다.
Heap 메모리를 재활용하기 위해서 더이상 참조 되지 않는 객체들을 메모리에서 제거하는 모듈 입니다. 개발자가 직접 메모리를 정리 하지 않아도 되어서 개발 속도가 향상 되는 장점이 있지만 Mark and  Sweep 이라는 과정에서 참조되지 않는 객체를 찾는 과정이 있는데 이 때 스레드가 중단 되어서 성능이 떨어지는 단점이 있습니다.


객체지향 프로그래밍에 대해서 설명해 볼 수 있나요? </br>
실제 세계의 사물들을 객체로 모델링하여 개발을 진행하는 프로그래밍 기법
가장 대표적인 언어로 Java가 있다.
캡슐화, 상속, 다형성 등과 같은 기법을 이용할 수 있다. 다형성은 동일한 키보드의 키가 다른 역할을 하는 것처럼 하나의 메소드나 클래스가 다양한 방법으로 동작하는 것을 의미한다.
절치지향 언어보다 실행속도가 느리다.

4가지 특징 추상화 , 캡슐화 , 상속성 , 다형성

절차지향 프로그래밍 물이 위에서 아래로 흐르는 것처럼 순차적인 처리를 중요시하는 프로그래밍 기법이다. 가장 대표적인 언어로 C언어가 있다. 컴퓨터의 처리구조와 유사해 실행속도가 빠르다. 코드의 순서가 바뀌면 동일한 결과를 보장하기 어렵다.


접근제어자에 대해서 설명해볼 수 있나요? </br>
접근 제어자 접근 가능 범위 설명
public 모든 클래스 클래스, 메서드, 또는 필드가 모든 다른 클래스에서 접근 가능.
protected 동일 패키지 및 하위 클래스 동일 패키지 내의 클래스와 이 클래스를 상속받은 하위 클래스에서 접근 가능.
default 동일 패키지 접근 제어자를 명시하지 않으면 기본 접근 수준은 default (package-private)로 설정되며, 동일 패키지 내의 클래스에서만 접근 가능.
private 동일 클래스 클래스 내부에서만 접근 가능.

공개범위는 public  >  protected  >  default(생략)  >  private 순


제네릭타입에 대해서 설명해볼 수 있나요? </br>
제네릭 타입(Generic Types)은 클래스나 메서드를 정의할 때, 사용할 데이터 타입을 미리 지정하는 것이 아니라, 인스턴스를 생성하거나 메서드를 호출할 때 구체적인 타입을 지정할 수 있도록 하는 기능입니다. 제네릭은 코드의 재사용성을 높이고, 컴파일 시 타입 안전성을 제공합니다.

제네릭 타입의 장점 1.타입 안전성: 컴파일 시 타입 검사를 통해 런타임 오류를 줄일 수 있습니다. 2.재사용성: 하나의 클래스나 메서드가 다양한 타입을 지원할 수 있습니다. 3.가독성: 코드의 가독성과 유지보수성을 높입니다.

제네릭 타입 설명 예시
<T> 일반적인 타입 파라미터 public class Box<T> { private T item; }
<E> 컬렉션의 요소 타입 public class List<E> { void add(E element); }
<K, V> 맵의 키와 값 타입 public class Map<K, V> { V get(K key); }
<N> 숫자 타입 public class Numeric<N extends Number> { N number; }
<T, U, V> 다중 타입 파라미터 public class Triple<T, U, V> { T first; U second; V third; }


함수형 인터페이스에 대해서 설명해볼 수 있나요? </br>
함수형 인터페이스(Functional Interface)는 하나의 추상 메서드만을 가지는 인터페이스를 의미합니다. 이러한 인터페이스는 Java 8에서 람다 표현식과 함께 도입되었으며, 람다 표현식의 대상 타입으로 사용할 수 있습니다. 함수형 인터페이스는 함수형 프로그래밍 스타일을 Java에 도입하기 위한 중요한 요소입니다.
함수형 인터페이스 설명 추상 메서드 예시
Predicate<T> 매개변수 T를 받아 boolean을 반환 boolean test(T t)
Predicate<Integer> isPositive = x -> x > 0;
System.out.println(isPositive.test(5)); // 출력: true
        
Function<T, R> 매개변수 T를 받아 R을 반환 R apply(T t)
Function<String, Integer> lengthFunction = String::length;
System.out.println(lengthFunction.apply("Hello")); // 출력: 5
        
Supplier<T> 매개변수를 받지 않고 T를 반환 T get()
Supplier<String> stringSupplier = () -> "Hello";
System.out.println(stringSupplier.get()); // 출력: Hello
        
Consumer<T> 매개변수 T를 받아서 처리하고 반환값 없음 void accept(T t)
Consumer<String> printConsumer = System.out::println;
printConsumer.accept("Hello"); // 출력: Hello
        
UnaryOperator<T> 입력값과 출력값의 타입이 동일한 함수 T apply(T t)
UnaryOperator<Integer> square = x -> x * x;
System.out.println(square.apply(5)); // 출력: 25
        
BinaryOperator<T> 두 개의 동일한 타입 매개변수를 받아 동일한 타입을 반환 T apply(T t1, T t2)
BinaryOperator<Integer> sum = (a, b) -> a + b;
System.out.println(sum.apply(3, 5)); // 출력: 8
        


Checked Exception, Unchecked Exception에 대해서 설명해볼 수 있나요? </br>
Checked Exception
체크드 익셉션은 컴파일러가 예외 처리를 강제하는 예외입니다. 즉, 체크드 예외가 발생할 가능성이 있는 코드에서는 반드시 예외 처리를 해야 합니다. 이러한 예외는 주로 프로그램 외부의 문제(예: 파일 입출력, 네트워크 통신 등)로 인해 발생합니다.

특징:

컴파일 시점에 예외 처리 여부를 검사.
Exception 클래스를 상속하지만, RuntimeException을 상속하지 않음.
반드시 try-catch 블록이나 throws 키워드를 사용해 예외를 처리해야 함.

Unchecked Exception
언체크드 익셉션은 컴파일러가 예외 처리를 강제하지 않는 예외입니다. 주로 프로그래머의 실수(예: 잘못된 타입 캐스팅, 배열 인덱스 초과 등)로 인해 발생합니다.

특징:

런타임 시점에 예외가 발생.
RuntimeException 클래스를 상속.
예외 처리를 강제하지 않지만, 필요에 따라 예외 처리를 할 수 있음.
구분 체크드 예외 (Checked Exception) 언체크드 예외 (Unchecked Exception)
상속 관계 Exception 클래스를 상속하나, RuntimeException을 상속하지 않음 RuntimeException 클래스를 상속
컴파일러 강제 여부 컴파일 시 예외 처리를 강제 컴파일 시 예외 처리를 강제하지 않음
주로 발생하는 상황 프로그램 외부의 문제 (파일 입출력, 네트워크 통신 등) 프로그래머의 실수 (잘못된 타입 캐스팅, 배열 인덱스 초과 등)
예외 처리 방법 try-catch 블록이나 throws 키워드를 사용하여 예외를 처리해야 함 예외 처리가 선택 사항이지만 필요에 따라 처리 가능
예시
        
import java.io.FileReader;
import java.io.IOException;

public class CheckedExceptionExample {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("somefile.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
        
public class UncheckedExceptionExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3};
        System.out.println(numbers[5]);  // ArrayIndexOutOfBoundsException 발생
    }
}
        


자바 리플렉션에 대해서 설명해볼 수 있나요? </br>
자바 리플렉션(Java Reflection)은 런타임에 클래스, 메서드, 필드 등을 동적으로 검사하고 조작할 수 있는 기능입니다. 리플렉션을 사용하면 프로그램 실행 중에 객체의 메타데이터(클래스, 메서드, 필드 등)를 분석하고, 이를 통해 동적으로 객체를 생성하거나 메서드를 호출할 수 있습니다.

주요 개념:
1. 클래스 정보 얻기:
   - `Class` 객체를 통해 클래스의 메타데이터를 얻을 수 있습니다.
   - 예: 
      ```java 
      Class clazz = Class.forName("com.example.MyClass"); 
      ```

2. 생성자 접근:
   - 클래스의 생성자를 통해 새로운 인스턴스를 동적으로 생성할 수 있습니다.
   - 예: 
     ```java
     Constructor<?> constructor = clazz.getConstructor(String.class);
     Object instance = constructor.newInstance("parameter");
     ```

3. 메서드 접근:
   - 클래스의 메서드 정보를 얻고, 동적으로 메서드를 호출할 수 있습니다.
   - 예:
     ```java
     Method method = clazz.getMethod("myMethod", String.class);
     Object result = method.invoke(instance, "argument");
     ```

4. 필드 접근:
   - 클래스의 필드 정보를 얻고, 필드 값을 읽거나 쓸 수 있습니다.
   - 예:
     ```java
     Field field = clazz.getField("myField");
     field.set(instance, "new value");
     Object value = field.get(instance);
     ```

5. 리플렉션의 장점:
   - 동적 모듈 로딩 및 객체 조작: 컴파일 타임에 알 수 없는 클래스나 메서드를 런타임에 동적으로 로드하고 사용할 수 있습니다.
   - 프레임워크 개발: 리플렉션을 이용하여 의존성 주입, 애너테이션 기반 설정 등 다양한 기능을 구현할 수 있습니다.

6. 리플렉션의 단점:
   - 성능 저하: 리플렉션은 일반적인 메서드 호출보다 느립니다.
   - 보안 문제: 접근 제어를 우회할 수 있으므로, 보안상 문제가 발생할 수 있습니다.
   - 유지보수 어려움: 코드 가독성이 떨어지고, 리플렉션을 과도하게 사용하면 유지보수가 어려워질 수 있습니다.

자바 리플렉션은 강력한 도구이지만, 필요할 때 신중하게 사용하는 것이 좋습니다.


Java 자료구조에 대해서 설명해보세요. </br>
# Java 자료구조 개요

## 자료구조란?
- **설명**: 자료구조(Data Structure)는 데이터를 효율적으로 저장하고 관리하기 위한 방법을 의미합니다. 다양한 형태의 자료구조를 통해 데이터를 체계적으로 저장하고, 필요할 때 빠르고 효율적으로 접근하거나 수정할 수 있습니다. 자바에서는 여러 기본적인 자료구조를 제공하며, 개발자는 이를 활용하여 최적화된 프로그램을 작성할 수 있습니다.

## 1. 배열 (Array)
- **설명**: 같은 타입의 데이터가 연속적으로 저장되는 자료구조입니다. 배열은 고정된 크기를 가지며 인덱스를 통해 요소에 접근합니다.
- **장점**: 인덱스를 사용한 빠른 접근.
- **단점**: 크기가 고정되어 있어 동적으로 크기를 조절할 수 없음, 삽입 및 삭제가 비효율적.

## 2. 리스트 (List)
- **설명**: 순서가 있는 데이터의 집합입니다. 자바에서 `ArrayList`와 `LinkedList`가 대표적인 리스트 구현체입니다.
    - **ArrayList**: 내부적으로 배열을 사용하여 구현됩니다. 인덱스를 통해 빠르게 접근할 수 있지만, 크기를 동적으로 변경할 수 있습니다.
    - **LinkedList**: 각 요소가 노드로 이루어져 있으며, 노드는 다음 요소에 대한 참조를 가집니다. 삽입과 삭제가 빠르지만 인덱스 접근은 느립니다.

## 3. 스택 (Stack)
- **설명**: 후입선출(LIFO, Last In First Out) 구조를 가지는 자료구조입니다. `push`로 요소를 추가하고, `pop`으로 가장 마지막에 추가된 요소를 제거합니다.
- **사용 사례**: 재귀 호출, 브라우저의 뒤로 가기 기능, 수식의 괄호 검사 등.

## 4. 큐 (Queue)
- **설명**: 선입선출(FIFO, First In First Out) 구조를 가지는 자료구조입니다. `offer`로 요소를 추가하고, `poll`로 가장 먼저 추가된 요소를 제거합니다.
- **변형**:
  - **우선순위 큐 (Priority Queue)**: 각 요소가 우선순위를 가지며, 높은 우선순위를 가진 요소가 먼저 처리됩니다.

## 5. 맵 (Map)
- **설명**: 키-값 쌍으로 데이터를 저장하는 자료구조입니다. `HashMap`, `TreeMap`, `LinkedHashMap` 등이 자바에서 사용됩니다.
  - **HashMap**: 해시 함수를 사용하여 키를 관리하며, 빠른 검색, 삽입, 삭제가 가능합니다.
  - **TreeMap**: 키를 자동으로 정렬하여 저장하며, 이진 검색 트리 기반으로 구현됩니다.
  - **LinkedHashMap**: 삽입 순서를 유지하며 저장합니다.

## 6. 셋 (Set)
- **설명**: 중복되지 않는 요소의 집합입니다. `HashSet`, `TreeSet`, `LinkedHashSet` 등이 있습니다.
  - **HashSet**: 해시 함수를 사용하여 요소를 관리하며, 빠른 검색, 삽입, 삭제가 가능합니다.
  - **TreeSet**: 요소를 자동으로 정렬하여 저장합니다.

## 7. 트리 (Tree)
- **설명**: 계층 구조를 가지는 자료구조입니다. 이진 트리, AVL 트리, 레드블랙 트리 등이 있습니다.



자바 컬렉션 프레임워크(Java Collection Framework)에 대해서 설명하고 List , Map , Set 에 대해서 각각 설명해보세요. </br>
# Java 컬렉션 프레임워크

## 1. 컬렉션 프레임워크란?
- **설명**: 자바 컬렉션 프레임워크는 자바에서 데이터 구조를 표준화된 방식으로 다루기 위해 제공하는 클래스와 인터페이스의 집합입니다. 이 프레임워크는 데이터를 저장, 검색, 정렬, 조작하는 다양한 자료구조 및 알고리즘을 포함하고 있습니다.
- **장점**:
  - **일관된 API**: 다양한 컬렉션을 다루기 위한 일관된 메서드를 제공합니다.
  - **성능 최적화**: 다양한 상황에 맞는 효율적인 자료구조와 알고리즘을 선택할 수 있습니다.
  - **타입 안정성**: 제네릭스를 사용하여 컴파일 시점에 타입을 체크할 수 있습니다.

## 2. 주요 컬렉션 인터페이스

### 2.1 List
- **설명**: List는 순서가 있는 요소의 집합입니다. 중복된 요소를 허용하며, 인덱스를 통해 각 요소에 접근할 수 있습니다.
- **구현 클래스**:
  - **ArrayList**: 배열 기반으로 구현된 리스트. 빠른 인덱스 접근과 동적 크기 조절이 가능.
  - **LinkedList**: 노드 기반으로 구현된 리스트. 요소의 삽입과 삭제가 빠름.
  - **Vector**: ArrayList와 유사하지만, 동기화를 지원하여 스레드 안전성을 보장.

### 2.2 Set
- **설명**: Set은 중복되지 않는 요소의 집합입니다. 순서가 보장되지 않으며, 각 요소는 고유합니다.
- **구현 클래스**:
  - **HashSet**: 해시 테이블 기반의 집합. 빠른 검색과 삽입이 가능.
  - **LinkedHashSet**: HashSet과 유사하지만, 요소의 삽입 순서를 유지.
  - **TreeSet**: 요소를 정렬된 상태로 저장하는 집합. 이진 검색 트리 기반.

### 2.3 Map
- **설명**: Map은 키-값 쌍으로 데이터를 저장하는 구조입니다. 각 키는 고유하며, 하나의 키에 대해 하나의 값만 매핑됩니다.
- **구현 클래스**:
  - **HashMap**: 해시 테이블 기반의 맵. 빠른 검색과 삽입이 가능.
  - **LinkedHashMap**: HashMap과 유사하지만, 삽입 순서를 유지.
  - **TreeMap**: 키를 자동으로 정렬하여 저장. 이진 검색 트리 기반.
  - **Hashtable**: HashMap과 유사하지만, 동기화를 지원하여 스레드 안전성을 보장.

## 3. List, Set, Map 비교

| 특성       | List                                          | Set                                         | Map                                      |
|------------|-----------------------------------------------|---------------------------------------------|------------------------------------------|
| **순서**   | 유지됨                                         | 유지되지 않음                               | 키에 대해 정의된 순서가 있을 수 있음     |
| **중복**   | 허용됨                                         | 허용되지 않음                               | 키는 중복되지 않으며, 값은 중복 가능     |
| **접근**   | 인덱스를 통한 요소 접근 가능                   | 인덱스를 통한 접근 불가                     | 키를 통한 값 접근 가능                   |
| **대표 구현 클래스** | `ArrayList`, `LinkedList`, `Vector`          | `HashSet`, `LinkedHashSet`, `TreeSet`      | `HashMap`, `LinkedHashMap`, `TreeMap`   |



Enum 에 대해서 설명해보세요. </br>
 Enum은 "Enumeration"의 약자다. Enumeration은 "열거, 목록, 일람표" 라는 뜻을 가지고 있으며, 보통 한글로는 열거형이라고 부른다. 즉, 열거형(enum)은 요소, 멤버라 불리는 명명된 값의 집합을 이루는 자료형이다


<summary>JVM 메모리 모델 & happens-before / volatile / synchronized</summary> </br> <pre> 핵심: 멀티스레드 환경에서 “최신값을 보장하느냐”와 “실행 순서를 보장하느냐” 문제.

JVM 메모리 구성

Thread별: Program Counter, Stack

공용: Heap(객체), Metaspace(클래스 메타), Code Cache 등

JMM(happens-before)

A의 쓰기가 B의 읽기보다 “논리적으로 먼저” 보장되면, B는 A의 최신값을 본다.

lock/unlock, volatile write→read, 스레드 시작/종료 등은 happens-before를 성립시킴.

volatile

가시성 보장(캐시 무시, 메인메모리 교환) + 재배치 금지(일부 순서 보장)

원자성은 보장 X (long/double 64bit는 보장되지만 복합 연산은 X)

synchronized

상호배제(Mutual Exclusion) + 진입/퇴장 시점의 happens-before 보장

짧은 임계구역이면 간단/안전, 과도한 사용은 경합 증가

면접 포인트: “공유변수는 volatile 또는 동기화 없이는 최신값을 못 볼 수 있다”를 실제 버그 예시(폴링 플래그, 더블체크 로킹 등)로 설명하면 좋다. </pre>

</details>

<summary>HashMap 내부 동작 & ConcurrentHashMap 차이</summary> </br> <pre> 1) HashMap - 해시→버킷 인덱싱, 충돌 시 체이닝(자바8: 버킷 길이 ≥ 8이면 트리화, O(logN)) - loadFactor 기본 0.75, 용량 2배 리사이즈 시 재해시 - 단일 스레드 기준 빠름, 멀티스레드 put/resize 동시엔 위험(데이터 손상 가능)

ConcurrentHashMap

세그먼트 락이 아닌 CAS/노드 락 기반으로 더 미세한 동시성

size()는 근사값(고비용 정밀 계산은 필요 시만), compute/merge 류 원자적 갱신 제공

null key/value 불가(명확성/경합 방지)

면접 포인트: “멀티스레드 쓰기엔 HashMap 금지, CHM의 compute/merge로 원자 갱신” 한 줄로. </pre>

</details>

<summary>equals / hashCode / compareTo 계약(Contract)</summary> </br> <pre> 1) equals 계약: 반사성/대칭성/추이성/일관성 + null에 대해 false 2) hashCode 계약: equals가 true면 hashCode도 동일해야 함 3) compareTo: 정렬 순서 부여. equals와 일관되지 않으면 정렬 컬렉션에서 이상 동작

함정: 키로 쓰는 객체의 필드를 변경하면 컬렉션에서 “유실”될 수 있음(해시 버킷이 바뀜). 대응: 키는 가급적 불변(immutable), equals/hashCode에 쓰는 필드는 불변 유지. </pre>

</details>

<summary>제네릭 & 와일드카드(PECS) – extends/super의 의도</summary> </br> <pre> PECS: “Producer Extends, Consumer Super” - 생산자(읽기)면 <? extends T>, 소비자(쓰기)면 <? super T>

예) void copy(List<? super T> dst, List<? extends T> src) { … }

추가:

타입 소거(Type Erasure)로 new T() 불가, 런타임 제네릭 정보 부분 소실

배열은 공변, 제네릭은 불공변 → List에 List 대입 불가

</pre> </details>

<summary>Optional 모범 사용</summary> </br> <pre> - 반환 타입 전용. 필드/매개변수로는 남용 금지(중첩 Optional, 직렬화 이슈) - null 대체 저장소로 쓰지 말기 - orElse vs orElseGet: orElse는 항상 인자 평가, orElseGet은 필요할 때만 평가(지연) - get() 사용 지양 → orElseThrow/map/flatMap/filter 조합으로 처리

면접 한 줄: “Optional은 ‘값이 없을 수도 있음’을 명시하는 반환 타입 컨벤션”이라고 정리. </pre>

</details>

<summary>Stream 병렬(Parallel)과 주의점</summary> </br> <pre> - parallel()은 공용 ForkJoinPool(및 분할 가능 데이터)에 적합 - CPU 바운드/큰 작업/비순차 처리에 유리, 작은 컬렉션·I/O 바운드는 손해 - 상태 있는 람다/공유 가변 객체 접근 금지(데이터 레이스) - 정렬/순서 보장 연산은 병렬 이점 감소

체크리스트:

데이터 크기/분할 비용

박싱/언박싱 빈도

순서 의존성

공용 풀 경쟁(서버 환경에선 전용 Executor 고려)

</pre> </details>

<summary>CompletableFuture 핵심 패턴</summary> </br> <pre> - thenApply(동기 변환), thenCompose(비동기 합성), allOf/anyOf(조합) - 예외 처리: exceptionally / handle(결과, 예외 모두 다룸) - 타임아웃: orTimeout, completeOnTimeout - 풀 분리: supplyAsync(…, executor)로 서비스별 Executor 주입

면접 포인트: “조합 가능성(합성) + 예외/타임아웃 전략”을 실제 API 호출 예시로 말하기. </pre>

</details>

<summary>ExecutorService & 쓰레드풀 설계</summary> </br> <pre> - CPU 바운드: 고정 크기 풀(Fixed, 코어 수 ±), I/O 바운드: Cached/크기 큰 풀 - 종료: shutdown() → awaitTermination() → 필요 시 shutdownNow() - submit은 Future 반환(예외는 Future에서), execute는 반환 없음 - 풀 누수 방지: 앱 종료 훅에서 정리, 장기 블로킹 작업은 전용 풀로 분리

면접 포인트: “풀 크기 = 작업 특성(CPU/I-O) 기반”과 “정상 종료 절차”를 한 줄로. </pre>

</details>

<summary>동기화 도구 비교: synchronized / ReentrantLock / ReadWriteLock</summary> </br> <pre> - synchronized: 간단/최적화 잘됨, 블록/메서드 단위 - ReentrantLock: tryLock(타임아웃), 조건변수(Condition), 공정성 옵션 - ReadWriteLock: 읽기 경쟁 높고 쓰기 적은 경우 유리(동시 다중 읽기)

결정 팁:

단순 임계구역 → synchronized

타임아웃/중단/조건 대기 필요 → ReentrantLock

읽기 비중 아주 높음 → ReadWriteLock

</pre> </details>

<summary>Concurrent 컬렉션 선택 가이드</summary> </br> <pre> - ConcurrentHashMap: 동시성 키-값 저장. compute/merge로 원자적 갱신 - CopyOnWriteArrayList: 읽기 빈번·쓰기 드물 때. 쓰기 비용 매우 큼(복사 발생) - BlockingQueue(Linked/Array): 생산자-소비자 패턴 - ConcurrentLinkedQueue: 가벼운 비블로킹 큐

면접 포인트: “읽기 위주면 CopyOnWrite…, 생산자-소비자면 BlockingQueue”. </pre>

</details>

<summary>불변 객체(Immutable) & 방어적 복사</summary> </br> <pre> 장점: 스레드 안전, 캐싱/공유 유리, equals/hashCode 안정 방법: - 모든 필드 final, setter 없음 - 컬렉션은 불변 래퍼(List.copyOf/Collections.unmodifiableList) - 외부로 내보낼 때 방어적 복사(특히 Date/배열)

최근 문법: record(Java 16+)로 값 객체 간결 정의(자동 equals/hashCode/toString) </pre>

</details>

<summary>java.time 모범 사용(LocalDate/Instant/ZonedDateTime)</summary> </br> <pre> - LocalDate/LocalDateTime: 시간대 정보 없음(시차/서머타임 변환 불가) - Instant: UTC 기준 절대 시각(서버/로그에 적합) - ZonedDateTime: 시간대 포함, DST 안전 변환

권장: 저장/전송은 Instant(또는 UTC ISO-8601), 표시 시 ZoneId로 변환. </pre>

</details>

<summary>try-with-resources & Suppressed Exceptions</summary> </br> <pre> - AutoCloseable 자원 자동 해제, 닫기 순서는 역순 - 본문 예외와 닫기 예외가 동시 발생하면 닫기 예외는 suppressed로 보관 - getSuppressed()로 진단 가능

예) try (InputStream in = …; OutputStream out = …) { … } </pre>

</details>

<summary>ClassLoader & 리소스 로딩</summary> </br> <pre> - 부모 위임 모델: App → Platform → Bootstrap - getResourceAsStream(“path/..”)는 classpath 기준, 파일경로와 혼동 금지 - 컨테이너/플러그인 환경에선 클래스 충돌 가능 → 의존 버전/범위 관리 중요

면접 포인트: “부모 위임 + classpath 리소스와 파일시스템 구분”. </pre>

</details>

<summary>String/CharSequence 성능 팁</summary> </br> <pre> - 반복 결합은 StringBuilder 사용(+ 루프 안에서 String 누적 금지) - StringBuffer는 동기화 비용, 단일 스레드에선 Builder가 적합 - intern() 과용 금지(메모리/GC 압박)

체크: 대량 포맷팅은 Formatter보다 StringBuilder + 미리 크기 예측이 유리. </pre>

</details>

<summary>직렬화(Serializable) 사용 시 주의</summary> </br> <pre> - 가능하면 도메인 직렬화 대신 JSON/Protobuf 등 명시적 포맷 권장 - 꼭 필요하면 serialVersionUID 명시, 민감정보는 transient - readObject/readResolve로 불변성/보안 보완 가능

면접 포인트: “내/외부 계약은 명시적 스키마(버전 관리) 사용 권장”. </pre>

</details>

<summary>애너테이션 & 메타애너테이션 / 리플렉션</summary> </br> <pre> - @Retention(SOURCE/CLASS/RUNTIME), @Target, @Repeatable - 런타임 처리: 리플렉션으로 애너테이션 읽어 동작 제어(DI, AOP, 검증 등) - 단점: 성능/가독성 저하 가능 → 핵심 경로에서 과용 금지 </pre>

<summary>NIO.2 (Files/Path/WatchService) & 대용량 I/O</summary> </br> <pre> - Files/Path: 파일 조작 유틸(복사/이동/워크) - WatchService: 디렉터리 변경 감시(생성/수정/삭제) - FileChannel/메모리 매핑(MappedByteBuffer): 대용량 처리/랜덤 접근 유리

면접 포인트: “대용량은 채널/버퍼, 변경감시는 WatchService”. </pre>

</details>

<summary>성능 측정: JMH / Flight Recorder(JFR) 기초</summary> </br> <pre> - “측정 없이 최적화 금지”: JMH로 마이크로벤치(워밍업/측정 분리) - 애플리케이션 실측: JFR + Mission Control로 프로파일(할당/잠금/GC) - GC 튜닝은 “목표 지연/처리량”을 먼저 정의 후 근거 기반으로 진행 </pre>

<summary>(최근 문법) switch 식/패턴 매칭/record/sealed(버전 정책에 따라)</summary> </br> <pre> - switch expression: 값 반환형, 화살표 구문 - instanceof 패턴 매칭: 캐스팅 축약 - record: 불변 데이터 캐리어 - sealed class: 상속 허용 범위 제한(모델 안전성)

주의: 팀/런타임 자바 버전 정책에 맞춰 사용. </pre>

</details>

<summary>Enum 에 대해서 설명해보세요.</summary> </br> <pre> Enum(Enumaration의 약자)은 “열거형”으로, 유한한 상수 집합을 타입으로 표현. 장점: - 타입 안전(임의 문자열/정수보다 안전), switch/Map 키로 적합 - 필드/메서드 포함 가능(상태·행동 캡슐화), 인터페이스 구현 가능 - 싱글턴 구현에도 사용(Effective Java 권장)

예) public enum OrderStatus { REQUESTED(100), APPROVED(200), REJECTED(400); private final int code; OrderStatus(int code){ this.code = code; } public int code(){ return code; } } </pre>

</details>