면접 준비

[기술면접] 1. Java

34suuuuu 2025. 4. 1. 20:35
목차

    1. Java의 특징  

    • Java는 객체 지향 프로그래밍 언어이다.
    • 기본 자료형 (byte, int, short, long, float, double, char, boolean...) 을 제외하고는 모든 요소들이 객체로 표현된다.

     장점

    • JVM(자바 가상 머신) 위에서 동작하기 때문에 운영체제에 독립적이다.
    • GarbageCollector를 통한 자동적인 메모리 관리가 가능하다.

    단점

    • JVM 위에서 동작하기 때문에 실행 속도가 상대적으로 느리다.
    • 다중 상속이나 타입에 엄격하며, 제약이 많다

    2. JVM의 역할  

    JVM은 스택 기반으로 동작하며 Java Byte Code를 OS에 맞게 해석해주는 역할을 하고 GarbageCollector를 통해 자동적인 메모리 관리를 한다.

     

    3. JVM의 클래스는 언제 로딩되는지 

    • JVM은 LAZY Loading 메커니즘을 사용한다. 
    • 클래스를 미리 메모리에 올리지 않고, 필요한 상황에 맞춰 동적으로 메모리에 올려 효율적으로 관리한다.
    • static 변수와 메서드
      • 인스턴스화 하지 않아도 사용 가능하며 클래스가 로드된다.
    • inner 클래스와 static inner 클래스
      • inner 클래스: outer 클래스를 인스턴스화 해야만 생성 가능하기 때문에 outer클래스와 inner클래스 둘 다 로드된다.
      • static inner클래스: outer클래스를 로드하지 않고 인스턴스화가 가능하다.
    • static final 키워드의 상수
      • 클래스가 로드되지 않고 사용 가능하다.
      • 컴파일 시점에 이미 값이 확정되고, 상수는 JVM의 Method Area의 Constant Pool에 따로 저장되어 관리되기 때문이다.
    • final 키워드의 상수
      • 런타임 시점에 값이 결정되므로 지역 변수일 경우 Stack에 저장되며 객체 생성시 초기화된다.

     

    4. JVM의 클래스는 언제 초기화 되는지 

    클래스 초기화 순서

    • 클래스의 인스턴스 생성
    • 클래스의 static 메서드 호출
    • 클래스의 static 변수 값 할당 및 사용

    클래스 인스턴스 초기화 순서

    • static 변수 초기화
    • static 블록 실행
    • 인스턴스 생성
    • 생성자 실행

     

    5. Java의 컴파일 과정  

    1. 개발자가 Java 소스코드(.java)를 작성한다.
    2. Java Compiler가 javac 명령어를 통해 Java 소스코드 파일을 읽어 바이트 코드(.class) 파일로 컴파일한다.
    3. 컴파일 된 바이트 코드(.class)를 JVM의 클래스로더(Class Loader)에 전달한다.
    4. 클래스로더는 필요한 클래스들만 JVM의 메모리 영역에 올린다.
    5. 실행 엔진은 JVM의 메모리에 올라온 바이트 코드(.class)를 명령어 단위로 하나씩 실행한다.

    ** 변환된 Byte Code는 기계어가 아니기 때문에 OS가 해석할 수 없기 때문에, JVM을 통해 Byte Code를 OS가 해석할 수 있는 기계어(Binary Code)로 변환한다.

    출처 - https://tutorial.eyehunts.com/java/how-java-program-run-java-work-compiler/

     

    6. Java에서 사용하는 원시 타입과 참조 타입의 차이점 

    원시 타입 (Primitive Type)

    • 실제 데이터 값을 저장하는 타입이다.
    • 즉, 스택 영역에 메모리 공간이 만들어지고 실제 데이터 값이 저장된다.
    • null 값을 담는 것이 불가능하다.
    • 값이 없는 경우 default값을 반환한다.

    참조 타입 (Reference Type)

    • 스택 영역에는 참조값만 존재하고 실제 값은 힙 영역에 존재한다.
    • 최소 2번 이상의 메모리 접근이 필요하므로 속도가 느리다 (e.f. Integer -> int)
    • null 값을 담을 수 있다.
    • Generic 타입에서 사용할 수 있다. `List<Integer> list`

     

    7. Java에서 제공하는 원시 타입들과 각각 차지하는 메모리  

    정수형

    • byte - 1byte
    • short - 2byte
    • int - 4byte
    • long - 8byte

    실수형

    • float - 4byte
    • double - 8byte

    문자형

    • char - 2byte

    논리형

    • boolean - 1byte

     

    8. Overriding vs Overloading  

    • 오버라이딩(Overriding)은 상위 클래스에 있는 메소드를 하위 클래스에서 재정의하는 것을 말한다.
    • 오버로딩(Overloading)은 매개변수의 개수나 타입을 다르게하여 같은 이름의 메소드를 여러 개 정의하는 것을 말한다.

     

    9. 객체 지향 프로그래밍 (OOP) 

    프로그램 구현에 필요한 데이터를 추상화시켜 상태(속성/ 어트리뷰트)와 행위(메서드)를 가진 객체고 만들고, 그 객체들 간의 상호작용을 통해 프로그램을 만드는 것을 의미한다.

     

    장점

    • 코드 재사용에 용이하다.
    • 유지보수가 쉽다.

    단점

    • 상대적으로 처리 속도가 느리다.
    • 설계시 많은 시간과 노력이 필요하다.

     

    10. 객체 지향 프로그래밍 4가지 특성 

    캡슐화

    • 객체의 속성을 보호하기 위해 사용된다.
    • 필요한 정보만을 노출하고 실제 내부 구현 정보는 숨긴다.
    • 객체의 데이터와 메서드를 하나로 묶고, 외부에서 객체의 내부 상태에 직접 접근을 제한한다.
    • 접근 제한자를 통해서 구현할 수 있다.

    상속

    • 상위 클래스로부터 속성과 메서드를 물려받는 것을 의미한다.
    • 상위 클래스에서 하위 클래스로 갈수록 구체화된다.

    다형성

    • 여러 클래스가 동일한 메서드를 다른 방식으로 구현할 수 있는 능력을 말한다.
    • 같은 인터페이스나 메서드가 다양한 방식으로 실행될 수 있게하여 프로그램의 유연성을 제공한다.
    • overloading이나 overriding을 통해 다형성 구현이 가능하다.

    추상화

    • 클래스들의 공통적인 특성만 묶어서 표현한다.

     

    11객체 지향 설계 원칙 

    • 변경에 용이하고, 유지 보수와 확장이 쉬운 소프트웨어 개발을 위해 필요하다.
    • 높은 응집도와 낮은 결합도가 객체 지향 설계의 핵심이다.

    SRP (Single Responsibility Principle) - 단일 책임 원칙

    • 한 클래스는 단 하나의 책임만 가져야한다.
    • 하나의 클래스에 여러 책임이 있다면 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향을 미칠 수 있어 유지보수성이 떨어진다.

    OCP (Open Closed Principle) - 개방 폐쇄 원칙

    • 소프트웨어 요소는 확장에는 열려있으나 수정에는 닫혀 있어야한다.
    • 기존의 코드를 변경하지 않고 기능을 수정, 추가할 수 있도록 설계해야한다.

    LSP (Liskov Substitution Priciple) - 리스코프 치환 원칙

    • 하위 타입은 언제나 상위 타입을 대체할 수 있어야한다.
    • 다형성 원리를 위한 개념이다.

    ISP (Interface Segregation Priciple) - 인터페이스 분리 원칙

    • 사용에 맞게 인터페이스를 잘 분리해야한다.
    • 하나의 일반적인 인터페이스보다 여러 개의 구체적인 인터페이스가 낫다.
    • 클라이언트의 목적과 용도에 적합한 인터페이스만을 제공하는 것을 목표로한다.

    DIP (Dependency Inversion Priciple) - 의존 역전 원칙

    • 구체적인 클래스보다 상위 클래스, 인터페이스, 추상 클래스와 같이 변하지 않은 가능성이 높은 클래스와 관계를 맺는것이 좋다.
    • 클래스간의 결합도를 낮추는 것을 지향한다.
    • 의존성 주입 (DI)

     

    12클래스 vs 객체  vs 인스턴스 

    클래스: 객체를 만들기 위한 코드, 틀, 명세와 같은 설계도

    객체: 클래스에 따라서 생성되며 자신의 고유한 상태(필드)와 행동(메서드)를 갖는다.

    인스턴스: 객체에 메모리가 할당되어 실제로 활용되는 실체

     

    13. try-with-resources란? 

    • try-catch-finally의 문제점을 보완하기위해 나온 개념이다.
    • try(...)안에 자원 객체를 전달하면, try블록이 끝나고 자동으로 자원 해제를 해주는 기능을 말한다.
    • finally구문이나 모든 catch구문에 종료를 하지 않아도 된다는 장점이 있다.

     

    14. 불변 객체는 무엇인지, 그리고 Java의 예시는 무엇이 있는지 

    • 불변 객체는 객체 생성 이후 내부의 상태가 변하지 않는 객체를 말한다.
    • 재할당을 가능하나 한번 할당하면 내부 데이터를 변경할 수 없는 객체를 말한다.
    • read-only 메서드만을 제공하며 객체의 내부 상태에  제공하는 메서드를 제공하지 않는다.
    • Java에서는 필드가 원시 타입인 경우 final 키워드를 이용해 불변 객체를 생성할 수 있고, 참조 타입의 경우에는 추가적인 작업이 필요하다.

     

    15. 참조 타입일 경우 추가적인 작업은 어떤게 있는지 

    참조 타입은 대표적으로 1) 객체 2) 배열이나 3) List 등을 참조하는 경우가 있다.

     

    1. 참조 변수가 일반 객체인 경우 객체를 사용하는 필드의 참조 변수도 불변 객체로 변경해야합니다.

    2. 배열일 경우 배열을 받아 copy해서 저장하고, getter를 clone으로 반환하도록 하면 된다.

    ** 배열을 그대로 참조하거나 반환할 경우 외부에서 내부 값을 변경할 수 있다. clone을 반환해 외부에서 값 변경하지 못하게한다.

    3. 리스트인 경우에도 배열과 마찬가지로 생성시 새로운 List를 만들어 값을 복사하도록 해야한다.

     

    16불변 객체나 final을 굳이 사용해야하는 이유

    1. Thread-safe하여 병렬 프로그래밍에 유용하며, 동기화를 고려하지 않아도 된다.

    Multi-Thread환경에서 동기화문제는 공유 자원을 동시에 쓰기(write)때문에 발생한다. 하지만 불변이라면 항상 동일한 값을 반환하기에 문제가 발생하지 않는다.

     

    2. 실패 원자적인 메소드를 만들 수 있다.

    어떤 예외가 발생하더라도 호출 전의 상태를 유지할 수 있어 동일한 상태로 다음 로직을 처리할 수 있다.

     

    3. 부수 효과를 피해 오류가능성을 최소화할 수 있다.

    부수효과: 변수의 값이나 상태 등의 변화가 발생하는 효과

    만약 setter를 통해 여러 객체들의 값을 변경한다면 이를 파악하기위해 메서드들을 살펴봐야한다.

    유지보수성을 위해 부수효과가 없는 순수 함수들을 만드는 것이 중요한데 객체가 불변이라면 이런 문제점을 해결할 수 있다.

     

    4. 메서드 호출 시 파라미터 값이 변하지 않는다는것을 보장할 수 있다. 

     

    5. 가비지 컬렉션의 성능을 높일 수 있다.

     

    17추상 클래스 vs 인터페이스 

    추상 클래스

    • 추상 메서드를 포함하거나 `abstract`로 정의 된 클래스다.
    • 자식 클래스에서 추상 메서드만을 오버라이딩해서 사용한다.
    • 상속받는 클래스들의 공통적인 로직을 추상화하고, 기능 확장을 위해 사용한다.
    • 단일 상속만 허용한다.
    • extends 키워드를 사용한다.

    인터페이스

    • 내부의 모든 메서드를 `public abstract` 로 정의한다. (생략 가능)
    • 내부의 모든 멤버 변수는 `public static final`로 정의한다. (생략 가능)
    • `static`, `default`, `private` 제어자를 붙여 클래스같이 구체적인 메서드를 가질 수 있다.
    • 미리 구현해야할 메서드를 지정함으로서 대규모 프로젝트 개발 시 일관되고 정형화된 개발을 위해 표준화한다.
    • 그 인터페이스를 구현하는 모든 클래스에 대해 특정 메서드가 반드시 존재하도록 강제함이 있다.
    • 다중 상속 가능한다.
    • implements 키워드를 사용한다.

    공통점

    • new 생성자 사용이 불가능하다.
    • 사용하기 위해서는 하위 클래스에서 추상 메서드를 반드시 구현해야한다. (강제성)

     

    18. 싱글톤 패턴이란? 

    프로그램 시작부터 종료까지 어떤 클래스의 인스턴스가 메모리 상에 단 하나만 존재할 수 있게 하고 이 인스턴스에 대해 어디에서나 접근 할 수 있도록 하는 디자인 패턴이다.

    인스턴스가 1개만 존재해야 한다는 것을 보장하고 싶은 경우와 동일한 인스턴스를 자주 생성해야하는 경우에 주로 사용한다. 이는 메모리 낭비 방지를 위함이다.

     

    19. 싱글톤 패턴의 대표적인 예시 

    싱글톤 패턴의 대표적인 예시는 SpringBean 이다.

    Spring의 빈 등록 방식은 싱글톤 스코프로, 기본적으로 모든 빈을 싱글톤으로 생성하여 관리한다.

    즉, 빈은 컨테이너에 한 번 생성되고, 생성된 객체는 single beans cache에 저장되게 된다.

    이후에 해당 빈에 대한 요청과 참조가 있는 경우 캐시 된 객체를 반환한다.

     

    20. Gabage Collection 이란?  

    Garbage Collection은 JVM의 메모리 관리 기법 중 하나로 시스템에서 동적으로 할당됐던 메모리 영역 중에서 필요없어진 메모리 영역을 회수하여 메모리를 관리해주는 기법이다.

     

    21. Garbage Collection 과정 

    1. Stop-The-World
      • GC를 수행하기 위해 JVM이 프로그램 실행을 멈추는 현상을 의미한다.
      • GC 관련 Thread를 제외한 모든 Thread가 멈추게되어 서비스 이용에 차질이 생길 수 있기 때문에, 이 시간을 최소화 해야한다.
      • 어떤 GC알고리즘을 사용하더라도 발생한다.
    2. Mark and Sweep
      • Mark: Root 객체에서 시작하여 참조되고 있는 객체와 그렇지 못한 객체를 구분한다.
      • Sweep: 참조하고 있지 않은 객체를 Heap에서 제거한다.
      • Compact: 분산된 객체들을 Heap의 시작 주소로 모아 메모리가 할당된 부분과 그렇지 않은 부분으로 압축한다 ( Garbage Collector의 종류에 따라 하지 않는 경우도 있다.)

     

    22. Java의 메모리 영역

    Method(Static) 영역

    • Class 정보, static 변수, 생성자, 메서드 등을 저장한다.
    • 프로그램 종료전까지 메모리상에 존재한다.
    • 어디서나 접근이 가능하다.

    Stack 영역

    • 기본 자료형, 지역 변수, 매개 변수가 저장되는 메모리 공간이다.
    • Heap 영역에 생성된 데이터의 참조값이 할당된다. 
    • 메서드가 호출될 때 메모리에 할당, 메서드 종료시 메모리에서 삭제된다.
    • Stack 구조를 가진다. (LIFO)

    Heap 영역

    • new 키워드로 생성된 객체, 배열 등이 저장된다.
    • JVM이 관리하는 프로그램 상에서 데이터를 저장하기 위해 런타임 시 동적으로 할당하여 사용하는 영역이다.
    • 보관되는 메모리가 호출이 끝나더라도 삭제되지 않고 유지된다. 하지만 어떤 참조 변수도 참조하지 않게 된다면, Gabage Collector에 의해 관리된다.

     

    23. 각 메모리 영역이 할당되는 시점은?   

    Method(Static) 영역: JVM이 동작해서 클래스가 로딩될 때 생성되어 프로그램이 종료될 때 메모리에서 삭제된다.

    Stack 영역: 메서드를 호출할 때마다 개별적으로 스택이 생성되며 종료시에 메모리에서 삭제된다.

    Heap 영역: 런타임시 할당하여 사용하고 호출이 끝나도 삭제되지 않고 유지된다. 그러다 어떤 참조 변수도 Heap 영역에 있는 인스턴스를 참조하지 않게 된다면 Garbage Collector에 의해 메모리에서 삭제된다.

     

    24. 생성자(Constructor) 란?  

    객체가 생성될 때 자동으로 호출되는 특수 목적의 메서드로 객체의 초기화를 위해 사용된다.

    • 생성자의 이름은 클래스의 이름과 동일해야 한다.
    • 리턴타입이 없다.
    • 파라미터를 다르게하여 오버로딩할 수 있다.
    • 클래스에 최소 1개가 필수적으로 필요하지만, 명시적으로 만들지 않은 경우에 컴파일러가 기본 생성자를 자동으로 생성한다. (만약 생성자 코드가 1개라도 작성되어 있다면, 컴파일러가 자동으로 생성하지 않는다.)

     

    25. Wrapper Class란 무엇이며, Boxing과 UnBoxing은 무엇인지 설명해주세요.  

    • 원시 타입을 객체화 한 것을 Wrapper Class라고 한다.
    • Boxing: 원시 타입을 Wrapper Class로 변환
    • UnBoxing: Wrapper Class를 원시 타입으로 변환

     

    26. Synchronized 란?  

    • 멀티 쓰레드 환경에서 여러 쓰레드가 하나의 공유 자원에 동시에 접근하지 못하도록 막는 개념이다.
    • 자바에서 Synchronized 키워드를 제공해 멀티 쓰레드 환경에서 쓰레드간 동기화를 시켜 데이터의 thread-safe를 보장한다.
    • Synchronized는 변수와 메소드에 사용해서 동기화 할 수 있으며, Synchronized 키워드를 남발하게 되면 오히려 프로그램의 성능저하를 일으킬 수 있다.

     

    27. new String()과 리터럴("")의 차이점  

    • new 연산자를 사용하면 객체로 생성되어 Heap 메모리 영역에 저장된다.
    • 리터럴을 사용하여 생성하면 String constant pool 이라는 영역에 생성된다. 
    • 리터럴을 사용하는 경우 같은 값이 존재한다면 이미 존재하는 값을 참조하게 된다.

     

    28. String, StringBuffer, StringBuilder의 차이  

    • String은 불변의 속성을 가지며 StringBuffer와 StringBuilder는 가변의 속성을 가진다.
    • StringBuffer는 동기화 키워드를 지원해 멀티쓰레드 환경에서 안전하다.
    • StringBuilder는 동기화를 지원하지않아 멀티 쓰레드 환경에서 사용할 수 없지만 싱글 쓰레드에서의 성능은 StringBuffer보다 뛰어나다.

     

    29. String객체가 불변인 이유  

    1. 캐싱 기능에 의한 메모리 절약과 속도 향상

    Java에서 String 객체들은 Heap의 String Pool이라는 공간에 저장되는데, 참조하려는 문자열이 이미 존재하는 경우 새로 생성하지 않고, 기존의 객체를 사용하기 때문에 특정 문자열 값을 재사용하는 빈도가 높을수록 상당한 성능 향상을 기대할 수 있다.

     

    2. Thread-safe

    String 객체는 불변이기 때문에 여러 쓰레드에서 동시에 특정 String 객체를 참조하더라도 안전하다.

     

    3. 보안 기능

    중요한 데이터를 문자열로 다루는 경우 강제로 해당 참조에 대한 문자열 값을 바꾸는 것이 불가능하기 때문에 보안에 유리하다.

     

    30. 접근제한자의 종류와 특징  

    • public : 접근 제한이 없어 같은 프로젝트 내에서 어디서든 사용 가능하다.
    • protected : 상속받은 클래스 또는 같은 패키지에서만 접근 가능하다. 
    • private : 같은 클래스에서만 접근 가능하다.
    • default : 기본 제한자로써 같은 패키지내에서만 접근이 가능하다.
    • public > protected > default > private 순서

     

    31. static 키워드   

    • static 키워드를 통해 생성된 변수나 메서드는 클래스가 로딩될 때 Static 영역에 메모리가 할당된 채 프로그램이 종료될 때 까지 삭제되지 않는다.
    • 즉, 인스턴스(객체) 생성없이 사용할 수 있다.
    • 모든 객체가 공유하는 메모리이다. 
    • Garbage Collector의 관리 영역 밖에 존재하므로 무분별한 static 키워드 남발은 메모리 누수를 불러올 수 있다.

     

    32. static을 사용하는 이유  

    • 생성할 때마다 인스턴스를 Heap에 올라가는 것이 아니라 고정 메모리이므로 값을 메모리에 로딩하거나, 읽어들이는 것보다 메모리를 효율적으로 관리할 수 있다.
    • 인스턴스 생성없이 사용이 가능하기 때문에 프로그램 내에서 공통으로 사용되는 데이터들을 관리할 때 이용한다.

     

    33. Inner Class의 장점  

    • 클래스가 여러 클래스와 관계를 맺지 않고 하나의 특정 클래스와만 관계를 맺는 경우 내부 클래스로 작성해 클래스를 논리적으로 그룹화할 수 있다.
    • 그룹화를 통해 캡슐화를 증가시키고 코드의 복잡성을 낮출 수 있다.
    • 내부 클래스에서 외부 클래스의 멤버들을 제약 없이 쉽게 접근할 수 있다.
    • 외부 클래스에서는 내부 클래스에 접근할 수 없어 코드의 보안성을 높일 수 있다.

     

    34. Inner Class를 static으로 해야하는 이유  

    • 외부 참조로 인한 메모리 누수 현상을 방지할 수 있다.
    • static이 아닌 내부 인스턴스 클래스는 외부와 연결 되어 있어 외부 참조를 갖게되고, GC 대상에서 제외되어 메모리를 차지하게된다
     

    35. 리플렉션(Reflection) 이란?  

    Reflection이란 구체적인 클래스 타입을 알지 못하더라도 해당 클래스의 메서드, 타입, 변수들에 접근할 수 있도록 해주는 자바 API다.

    즉, 객체를 통해서 클래스의 정보를 분석해내는 개념이다.

     

    36. 리플렉션(Reflection) 은 어떤 경우에 사용되는지  

    코드를 장석할 시점에는 어떤 타입의 클래스를 사용할 지 모르지만, 런타임 시점에 지금 실행되고 있는 클래스를 가져와서 실행해야 하는 경우 사용된다. 

    프레임워크나 IDE에서 이런 동적인 바인딩을 이용한 기능을 제공한다. 

    IntelliJ의 자동완성 기능, 스프링의 어노테이션이 reflection을 이용한 기능이라 할 수 있다.

     

    37. Error와 Exception의 차이  

    Error

    • 예측이 불가능하고 만약 발생하면 복구할 수 없는 심각한 오류를 말한다.
    • 오류가 발생하면 프로그램이 비정상적으로 종료된다.
    • 대부분의 에러는 JVM에서 발생한다.
    •  메모리 부족 (OutOfMemoryError),스택오버플로우 (StackOverFlowError) 등이 있다.

    Exception

    • 수습될 수 잇는 비교적 덜 심각한 오류를 말한다.
    • 예외 처리 문법(try-catch)을 사용해 예외의 발생을 대비할 수 있다.
    • 컴파일 에러와 런타임 에러로 구분된다.

     

    38. CheckedException과 UnCheckedException의 차이  

    CheckedException

    • 컴파일 예외 클래스를 말한다.
    • 반드시 예외 처리가 필요하다.
    • RuntimeException을 제외한 Exception 클래스와 그를 상속받는 하위 예외 클래스가가 있다.
      • IOException
      • FileNotFoundException
      • SQLEException

    UnCheckedException

    • 런타임 예외 클래스를 말한다.
    • 명시적인 처리를 안해줘도 된다.
    • UnCheckedExceptiondmf 상속한 RuntimeException 클래스와 과 그 하위 예외 클래스가 있다.
      • NullPointerException
      • IllegalArgumentException
      • IndexOutOfBoundException
      • SystemException

     

    39. Optional API란?  

    • NPE(NullPointerException)을 피하기 위해 사용한다.
    • 특정 객체가 없을지도 모른다 즉,null 값일지도 모른다는 것을 명시적으로 표현하기위한 클래스다.
    • Optional<T>는 null이 올 수 있는 값을 감싸는 Wrapper 클래스로 Generic을 통해 null 값이더라도 예외가 발생하지 않는다.

     

    40. Collection 프레임워크란?  

    • 다수의 데이터를 쉽고 효과적으로 관리할 수 있는 표준화된 방법을 제공하는 클래스의 집합을 의미합니다.
    • 자바 컬렉션에는 List, Set, Map 인터페이스를 기준으로 여러 구현체가 존재하고, 이에 더해 Stack, Queue 인터페이스도 존재합니다.
    • 즉, 자료 구조 종류의 형태들을 Java 클래스로 구현한 것을 말한다.

    41List, Set, Map 의 특징  

    List 인터페이스

    • 저장 순서가 유지되는 데이터의 집합이다.
    • 같은 요소의 중복 저장을 허용한다.
    • 배열과 마찬가지로 인덱스로 접근이 가능하다.
    • 자료형 크기가 데이터 양에 따라 동적으로 변한다.
    • 요소 사이의 빈 공간을 허용하지 않아 삽입/ 삭제 시 배열 이동이 발생하다.
    • 대표적인 구현체로는 ArrayList, LinkedList, Stack, Vector, Queue 등이 있다.

    Set 인터페이스

    • 데이터의 중복을 허용하지 않고 순서가 없는 데이터의 집합이다.
    • 순서를 보장하기 위해서는 LinkedHashSet을 구현체로 사용한다.
    • 검색, 정렬, 범위 검색의 높은 성능을 위해서는 데이터를 정렬하여 저장하는 TreeSet을 사용한다.
    • 대표적인 구현체로는 HashSet, LinkedHashSet, TreeSet 등이 있다.

    Map 인터페이스

    • 키(key) - 값(value)의 쌍으로 연관지어 데이터를 저장한다.
    • 키를 기준으로 중복을 허용하지 않으며 만약 중복된 키에 대해서 다른 값을 저장하면 가장 최근 저장한 값이 남게된다.
    • 순서가 유지되지 않는다.
    • 대표적인 구현체로는 HashMap, LinkedHashMap, Hashtable, TreeMap 등이 있다.

     

    42. Set과 Map의 타입이 Wrapper Class가 아닌 Object를 받을 때 중복 검사는 어떻게 해야하는지  

    hashCode() 메소드를 오버라이딩하여 리턴된 해시코드 값이 같은지를 보고 해시코드 값이 다르다면 다른 객체로 판단하고,
    해시코드 값이 같으면 equals() 메소드를 오버라이딩하여 다시 비교한다. 이 두 개가 모두 맞으면 중복이다.

     

    43. Vector와 List의 차이점  

    Vector

    • 삽입 시 이후 데이터들을 뒤로 이동한 후 삽입하기 때문에 시간복잡도 측면에서 List보다 성능이 떨어진다.
    • 인덱스를 통해 접근이 가능하다. 
    • 동기화 항상 동기화되기 때문에 멀티 쓰레드 환경에서 안전(Thread safe)하게 사용할 수 있다. 하지만 단일 쓰레드 환경에서 동기화를 하기 때문에 List보다 성능이 떨어진다.

     

    List

    • 헤드와 테일 정보를 담고있는 노드들의 연결로 이루어졌다.
    • 포인터를 통해 데이터의 위치를 가르키고 있어 삽입, 삭제가 용이하다.
    • 인덱스 접근이 불가능하기 때문에 처음부터 순차적으로 탐색해야하기 때문에 Vector에 비해 성능이 떨어진다.
    • 동기화 처리가 안되기 때문에 멀티 쓰레드 환경에서 안전하지 않다.
      삽입/ 삭제 검색 멀티 스레드 싱글 쓰레드
    Vector
    List

     

    44. Generic이란? 왜 써야하는가  

    • 제네릭은 데이터의 타입을 하나로 지정하지 않고 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법이다.
    • 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.
    • 클래스 외부에서 타입을 지정해주기 때문에 따로 체크하고 변환해 줄 필요가 없다.

     

    45. Generic의 불공변성이란?  

    Generic 타입은 상하관계가 없어 캐스팅이 불가능하다. 즉, Generic은 전달받은 딱 그 타입으로만 서로 캐스팅이 가능하다.

    하지만 와일드카드를 이용하면 컴파일러 트릭을 통해 불공변성을 유연하게 처리할 수 있다.

    • <? extends T> : 상한 경계 와일드카드로 공변성 적용
    • <? super T> : 하한 경계 와일드카드로 반공변성 적용

     

    캐스팅이 되는 경우

    Object parent = new Object();
    Integer child = new Integer(1);
    
    parent = child; // 다형성 (업캐스팅)

     

    캐스팅이 안되는 경우

    ArrayList<Object> parent = new ArrayList<>();
    ArrayList<Integer> child = new ArrayList<>();
    
    parent = child; // ! 업캐스팅 불가능
    child = parent; // ! 다운캐스팅 불가능

     

     

    46. final / finally/ finalize의 차이점은?  

    final

    • 클래스, 메서드, 변수, 인자를 선언할 때 사용할 수 있으며, 한 번만 할당하고 싶을 때 사용한다.
    • final 변수 :  한 번 초기화되면 그 이후에 변경할 수 없다.
    • final 메서드 : 다른 클래스가 이 클래스를 상속할 때 메소드 오버라이딩 할 수 없다.
    • final 클래스 : 다른 클래스에서 이 클래스를 상속하는 것을 금지한다.

    finally

    •  try-catch 블럭에서 사용되는 예약어로, 예외 발생 여부와 관계없이 항상 실행되는 코드 블록을 나타낸다.

    finalize

    • Java Garbage Collector에서 더 이상의 참조가 존재하지 않는 객체를 발견하는 순간 호출하는 메서드다. 
    • 하지만 메서드의 호출 시점이 불분명하기 때문에 해당 메서드가 실행된다는 보장이 없어서  OOME(Out of Memory Exception)이발생할 수 있어 finalize() 메소드를 오버라이딩하여 구현하는 것을 권장하지 않고 있습니다

     

    47. 직렬화(Serialize) 란?  

    • 시스템 내부에서 사용되는 객체 또는 데이터를 외부의 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술이며, 반대로 직렬화된 바이트 형태의 데이터를 다시 객체로 변환하는 과정을 역직렬화라고 한다.
    • 즉, JVM의 힙(heap) 혹은 스택(stack) 메모리에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술을 말한다.

     

    48. SerialVersionUID를 선언해야 하는 이유  

    • JVM은 직렬화와 역직렬화를 하는 시점의 클래스에 대한 버전 번호를 부여하는데, 만약 그 시점에 클래스의 정의가 바뀌어 있다면 새로운 버전 번호를 할당하게 된다. 그래서 직렬화할 때의 버전 번호와 역직렬화를 할 때의 버전 번호가 다르면 역직렬화가 불가능하게 될 수 있기 때문에 이런 문제를 해결하기 위해 SerialVersionUID를 사용한다.
    • 만약 직렬화할 때 사용한 SerialVersionUID의 값과 역직렬화 하기 위해 사용했던 SVUID가 다르다면 InvalidClassException이 발생할 수 있다.

     

    49. 인스턴스 초기화 블럭과 정적 초기화 블럭의 차이점  

    특징 인스턴스 초기화 블럭 정적 초기화 블럭
    실행 시점 객체가 생성되기 직전 클래스가 처음 로드될 때
    실행 횟수 객체가 생성될 때마다 실행 한 번만 실행
    사용 목적 객체별 공통 초기화 코드 작성 정적 변수 초기화 또는 클래스 단위 작업, 예외 처리
    키워드 {  } static {  }

     

     

     


    참고 포스팅