📚 Java 핵심 Q&A + 자료 구조 & 메모리/쓰레드 정리
🗂️ 자료 구조 & Java 메모리/쓰레드 핵심 정리
Q. 자료 구조 비교 : HashMap ↔ HashTable
| 구분 | HashMap 🚀 | HashTable 🛡️ |
|---|
| 동기화 | ❌ 지원하지 않음 (싱글스레드에 적합) | ⭕ 기본적으로 동기화 지원 (멀티스레드 적합) |
| null 허용 | key: 1개, value: 여러 개 허용 ✅ | key, value 모두 null 불가 ❌ |
| 성능 | 더 빠름 ⚡ | 상대적으로 느림 🐢 |
Q. ArrayList ↔ LinkedList
| 구분 | ArrayList 🧩 | LinkedList 🧵 |
|---|
| 구조 | 배열 기반 | 노드 기반(연결 리스트) |
| 조회 속도 | 인덱스 조회: O(1) ⚡ | 인덱스 조회: O(n) 🐌 |
| 삽입/삭제 | 중간 삽입/삭제: O(n) 🐢 | 중간 삽입/삭제: O(1) ⚡ |
| 사용 케이스 | 조회가 빈번할 때 📖 | 삽입/삭제가 빈번할 때 ✏️ |
개념적으로는 위의 내용과 동일하지만, 사실 성능면에서는 둘은 큰 차이가 없다.
- ArrayList는 리사이징 과정에서 배열 복사하는 추가 시간이 들지만, 배열을 새로 만들고 for 문을 돌려 기준 요소를 일일히 대입하는 처리가 아니기 때문에, 내부적으로 잘 튜닝이 되고 최적화 되어 있어서 눈에 띄게 LinkedList보다 느리지 않기 때문에 실제로 ArrayList를 사용하는 경우가 많다!!!
Q. JVM이란? 🤖
A.
- JVM은 Java Virtual Machine의 약자입니다.
- JVM은 OS에 종속받지 않고 Java 클래스 파일을 로드하고 바이트 코드를 해석합니다.
- JVM은 메모리 등 자원을 할당·관리·처리하는 프로그램입니다.
Q. JVM 동작 구조 🏗️
A.
- 프로그램 실행 🏃♂️: JVM이 운영체제로부터 필요한 메모리를 할당받습니다.
- 컴파일 🔄: 자바 컴파일러(javac)가 소스 코드(.java)를 바이트코드(.class)로 변환합니다.
- 로딩 📦: Class Loader가 class 파일을 JVM에 로딩합니다.
- 실행 🚀: Execution Engine이 바이트코드를 해석 및 실행합니다.
- 인터프리터 방식 또는 JIT(Just-In-Time) 컴파일 방식을 사용합니다.
- 메모리 배치 🧠: 실행된 바이트코드는 Runtime Data Areas에 배치되어 실제 수행이 이루어집니다.
- 관리 🛠️: JVM은 가비지 컬렉션(GC), 스레드 동기화 등 관리 작업을 수행합니다.
Q. GC(Garbage Collection) 개념 🗑️
A.
- 가비지컬렉션은 JVM이 불필요한 메모리를 자동으로 해제하는 기능입니다.
- Heap 영역은 객체 저장, 새 객체는 Young Generation에 위치합니다.
- Minor GC는 Young Generation에서 주기적으로 발생하며, 사용하지 않는 객체를 정리합니다.
- Major GC는 여러 번 살아남은 객체가 Old Generation으로 이동한 후, 이 영역에서 발생합니다.
Q. Java의 메모리 영역 🧠
A.
| 영역 | 설명 | 공유 여부 |
|---|
| Method Area | 클래스 메타데이터, static 변수, 상수 풀 등 | 모든 스레드 공유 👥 |
| Heap Area | new로 생성된 인스턴스 저장 | 모든 스레드 공유 👥 |
| Stack Area | 메서드 호출 시 프레임 쌓임, 지역 변수 저장 | 스레드별 생성 🧵 |
| PC Register | 현재 실행 중인 명령어 주소 기록 | 스레드별 생성 🧵 |
| Native Method Stack | 네이티브 코드 호출 시 사용 | 스레드별 생성 🧵 |
Method Area, Heap Area는 모든 스레드가 공유합니다.
Stack, PC Register, Native Method Stack은 스레드별로 생성됩니다.
Q. Java의 쓰레드 → 멀티쓰레드 → Synchronized 키워드 🧵
A.
- 멀티스레드는 하나의 프로세스에서 여러 작업을 동시에 처리할 수 있습니다.
- 멀티스레드의 장점은 CPU 자원을 효율적으로 활용할 수 있다는 점입니다.
- 멀티스레드의 문제점은 여러 스레드가 공유 자원에 동시 접근 시 동기화 문제가 발생할 수 있다는 점입니다.
- 해결책으로
synchronized 키워드를 사용하여 공유 자원의 일관성을 보장합니다.
🔍 Java 기본 Q&A
Q. 가비지컬렉션이란? 🗑️
A.
- 가비지컬렉션은 JVM에서 메모리 관리를 해주는 모듈입니다.
- 가비지컬렉션은 더 이상 참조되지 않는 객체들을 Heap 메모리에서 자동으로 제거합니다.
- 가비지컬렉션은 메모리를 재활용하는 기능입니다.
Q. 자바 메모리 구조는? 🧠
A.
- 자바 메모리 구조는 스레드별 영역과 공통 영역으로 구분됩니다.
- 스레드별 영역
- PC 레지스터 🧵: 현재 실행 중인 명령어 주소를 저장합니다.
- JVM 스택 🏗️: 메소드 호출 시 생성되는 프레임으로 매개변수, 지역변수, 리턴정보 등을 저장합니다.
- 네이티브 메소드 스택 🌐: 자바 외 언어로 작성된 네이티브 코드를 실행할 때 사용됩니다.
- 공통 영역
- 메소드 영역 📚: 클래스 정보, 정적 변수 등이 저장됩니다.
- 힙(Heap) 📦: 실행 중에 동적으로 생성되는 객체들이 저장되며, 가비지컬렉션에 의해 관리됩니다.
- 예시:
- new로 생성한 객체는 힙에 저장됩니다.
- 메소드 내 지역변수는 스택에 저장됩니다.
Q. Primitive Type과 Reference Type의 차이점은? 🧩
A.
| 구분 | Primitive Type (기본형) | Reference Type (참조형) |
|---|
| 종류 | int, boolean, double 등 8개 | 클래스, 배열, 인터페이스 |
| 저장 위치 | 스택 메모리 | 힙 메모리 |
| 특징 | 실제값 저장 | 객체의 주소(참조) 저장 |
Q. Java의 객체지향 4대 특징은? 🏗️
A.
- 캡슐화(Encapsulation) 🔒
- 접근 제어자를 통해 데이터를 은닉하고 외부에서 직접 접근하지 못하게 합니다.
- 상속(Inheritance) 🧬
- 부모 클래스의 속성과 기능을 자식 클래스가 물려받습니다.
- 다형성(Polymorphism) 🔄
- 같은 이름의 메소드나 클래스를 다양한 방식으로 구현합니다.
- 추상화(Abstraction) 🎯
- 객체의 중요한 부분만 드러내고 불필요한 세부사항을 숨깁니다.
Q. 오버로딩과 오버라이딩의 차이점은? 🔄
A.
| 구분 | 오버로딩 (Overloading) | 오버라이딩 (Overriding) |
|---|
| 정의 | 같은 이름, 다른 매개변수 | 상속받은 메소드 재정의 |
| 조건 | 매개변수 타입/개수 다름 | 이름, 매개변수, 리턴타입 동일 |
| 목적 | 다양한 입력값 처리 | 부모 클래스 메소드 변경/확장 |
Q. 오버로딩을 사용하는 이유는?
A.
- 오버로딩을 사용하는 이유는 메소드 이름을 일관성 있게 유지하면서 다양한 입력값을 처리할 수 있기 때문입니다.
- 오버로딩을 사용하는 이유는 코드의 유연성 및 확장성이 향상되기 때문입니다.
Q. 오버라이딩을 사용하는 이유는?
A.
- 오버라이딩을 사용하는 이유는 상속받은 부모 클래스의 메소드를 자식 클래스에서 재정의할 수 있기 때문입니다.
- 오버라이딩을 사용하는 이유는 다형성을 활용하여 같은 메소드 호출이지만 서로 다른 동작을 구현할 수 있기 때문입니다.
- 오버라이딩을 사용하는 이유는 코드의 유연성과 재사용성이 높아지기 때문입니다.
Q. 컬렉션 프레임워크 List, Set, Map의 차이는? 📚
| 구분 | List | Set | Map |
|---|
| 순서 | ✅ 입력 순서 보장 | ❌ (구현체에 따라 다름) | ❌ 기본은 순서 없음 (구현체에 따라 다름) |
| 중복 | ✅ 허용 | ❌ 허용하지 않음 | ❌ Key 중복 불가 / ✅ Value 중복 가능 |
| 저장 | 값(Value) | 값(Value) | 키-값(Key-Value) 쌍 |
🔍 Map 주요 구현체 차이
| 구현체 | 순서 보장 | 정렬 여부 |
|---|
HashMap | ❌ 순서 보장 없음 | ❌ 정렬 없음 |
LinkedHashMap | ✅ 삽입 순서대로 순서 보장 | ❌ 정렬 없음 |
TreeMap | ❌ 삽입 순서와 무관 | ✅ Key 기준 정렬 |
🔍 Set 주요 구현체 차이
| 구현체 | 순서 보장 | 정렬 여부 |
|---|
HashSet | ❌ 순서 보장 없음 | ❌ 정렬 없음 |
LinkedHashSet | ✅ 삽입 순서대로 순서 보장 | ❌ 정렬 없음 |
TreeSet | ❌ 삽입 순서와 무관 | ✅ 요소 정렬됨 (Comparable / Comparator 기준) |
- List → 순서 O, 중복 O → 배열처럼 사용
- Set → 순서 X, 중복 X → 수학적 집합
- Map → key-value 구조, key 중복 X, value 중복 O → 사전(Dict) 느낌
Q. 배열과 ArrayList의 차이점은? 🧩
A.
- 배열은 크기가 고정되어 있습니다.
- ArrayList는 동적으로 크기가 변하는 컬렉션입니다.
Q. null처리 시 주의할 점은? ⚠️
A.
- null처리 시에는 null 참조로 인한 NullPointerException을 방지해야 합니다.
- null처리 시에는 null 체크를 반드시 하거나 Optional 클래스를 활용해야 합니다.
Q. Call by reference와 Call by Value의 차이점은? 🔄
A.
| 구분 | Call by Value | Call by Reference |
|---|
| 전달 방식 | 값 복사 | 주소(참조) 전달 |
| 메소드 내 변경 영향 | 호출자 변수 영향X | 호출자 변수 영향O |
| Java/Spring | Call by Value 방식 사용 | - |
Q. 깊은 복사와 얕은 복사의 차이점은? 📋
A.
- 깊은 복사는 객체와 내부 참조 객체까지 모두 새로 복사하여 복사된 객체가 원본과 완전히 독립적으로 존재하는 방식입니다.
- 얕은 복사는 객체의 필드 값만 복사하고 참조형 객체가 있다면 주소값을 복사하여 원본 객체와 복사된 객체가 같은 참조 객체를 공유하는 방식입니다.
Q. 복사 개념과 Call by X의 개념의 차이 🔗
A.
❌ 같은 개념은 아니지만, “참조를 공유하느냐”는 점에서 관련 있음!
| 항목 | Call by Value / Reference | 깊은 복사 / 얕은 복사 |
|---|
| 적용 맥락 | 함수 인자 전달 시 | 객체 복사 시 |
| 핵심 차이 | 함수 내에서 원본에 영향을 미치는지 | 복사된 객체가 원본과 독립적인지 |
| 공통점 | 참조형 데이터를 전달하면 원본과 공유될 수 있음 | 얕은 복사는 참조형 필드를 원본과 공유함 |
| 차이점 | 함수 호출 시점의 전달 방식 | 객체 복사의 깊이에 대한 방식 |
Call by Value / Reference → 함수 호출 시 인자 전달 방식
깊은 복사 / 얕은 복사 → 객체 복사 시 원본과 독립적인지의 여부
Q. equals()와 hashCode()의 차이점은? 🔍
A.
- hashCode는 객체를 식별하기 위해 정수값을 반환하며, 주로 해시 기반 컬렉션에서 빠른 검색에 사용됩니다.
- equals는 두 객체가 논리적으로 같은지 비교하는 메소드로, 동일한 값을 가지는 객체인지를 확인할 때 사용됩니다.
- equals()를 오버라이딩하면 반드시 hashCode()도 함께 오버라이딩해야 합니다.
- HashSet이나 HashMap에서 제대로 동작하지 않기 때문