Java 자바 면접 준비 (feat. 상식)

업데이트:
9 분 소요

Java

1. Java의 특징

  • Java는 객체지향 프로그래밍 언어이다.
  • 기본 자료형을 제외한 모든 요소들이 객체로 표현되고, 객체 지향 개념의 특징인 캡슐화, 상속, 다형성이
    잘 적용된 언어이다.

1) 장점

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

가비지 컬렉션 (Garbage Collection)

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

가비지 컬렉션 과정

  • JVM이 어플리케이션의 실행을 잠깐 멈춘다.
  • GC를 실행하는 쓰레드를 제외한 모든 쓰레드들의 작업을 중단 후 (Stop The World 과정)
  • 사용하지 않는 메모리를 제거 (Mark and Sweep 과정)후 작업이 재개
  • GC의 작업은 Young 영역에 대한 Minor GC와 Old 영역에 대한 Major GC로 구분된다.

2) 단점

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

2. JVM의 역할

  • JVM은 스택 기반으로 동작한다.
  • Java Byte Code를 OS에 맞게 해석 해주는 역할을 한다.
  • 가비지 컬렉션을 통해 자동적인 메모리 관리를 해준다.

3. Java의 컴파일 과정

  • 개발자가 .java 파일을 생성한다.
  • build를 한다.
  • java compiler의 javac의 명령어를 통해 바이트코드 .class를 생성한다.
  • Class Loader를 통해 JVM 메모리 내로 로드한다.
  • 실행엔진을 통해 컴퓨터가 읽을 수 있는 기계어로 해석된다. (각 OS에 맞는 기계어)

4. Java에서 제공하는 원시 타입

1) 정수형

  • byte : 1 byte
  • Short : 2 byte
  • int : 4 byte
  • Long : 8 byte

2) 실수형

  • float : 4 byte
  • double : 8 byte

3) 문자형

  • char : 2 byte

3) 논리형

  • boolean : 1 byte

5. Overriding(오버라이딩) vs Overloading(오버로딩)

1) Overriding

  • 상위 클래스에 있는 메소드를 하위 클래스에서 재정의 하는 것

2) Overloading

  • 매개변수의 개수나 타입을 다르게 하여 같은 이름의 메소드를 여러 개 정의 하는 것

6. 객체지향 프로그래밍 (OOP)란?

  • 역할과 책임으로 나눈다.
  • 모든 데이터를 객체취급하여, 처리요청을 받은 객체는 객체 그안의 기능을 사용해 요청에 응답한다.
  • 특징으로는 캡슐화, 다형성, 상속, 추상화 등이 있다.
  • 모듈 재사용으로 확장 및 유지보수가 용이하다.

7. try - with - resources

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

8. 불변 객체

  • 불변 객체는 객체 생성 이후 내부의 상태가 변하지 않은 객체를 말합니다.
  • Java에서는 필드가 원시 타입인 경우 fianl를 사용해 불변 객체를 만든다.
  • 참조 타입일 경우엔 추가적인 작업 필요

9. 추상 클래스와 인터페이스의 차이

  • 추상 클래스는 클래스 내 추상 메소드가 하나 이상 포함되거나 abstract로 정의됨
  • 인터페이스는 모든 메소드가 추상 메소드로만 이루어져 있음

1) 공통점

  • new 연산자로 인스턴스 생성 불가능
  • 사용하기 위해서 하위 클래스에서 확장/구현 해야한다.

2) 차이점

  • 인터페이스는 그 인터페이스를 구현하는 모든 클래스에 대해 특정한 메소드가 반드시 존재해야 함.
  • 추상클래스는 상속받는 클래스들의 공통적인 로직을 추상화 시키고, 기능확장을 할 수 있음
  • 추상 클래스는 다중 상속 x , 인터페이스는 다중 상속 o

10. 싱글톤 패턴

  • 싱글톤 패턴은 단 하나의 인스턴스를 생성해 사용하는 디자인 패턴
  • 인스턴스가 1개만 존재해야 한다는것을 보장하고 싶은 경우 사용
  • 동일한 인스턴스를 자주 생성해야 하는 경우에 주로 사용 (메모리 방지 낭비)

1) 대표적인 예시

  • Spring Bean
  • 스프링 빈 등록 방식은 기본적으로 싱글톤 스코프이고, 스프링 컨테이너는 모든 빈들을 싱글톤으로 관리
  • 새로운 객체 -> @Scope(“prototype)

11. 객체지향 설계원칙

1) SRP - 단일 책임 원칙

  • 한 클래스는 하나의 책임만 가진다.

2) OCP - 개방-폐쇄 원칙

  • 확장에는 열려있고, 수정에는 닫혀있어야 한다.

3) LCP - 리스코프 치환 원칙

  • 상위 타입은 항상 하위 타입으로 대체 가능해야 한다.

4) ISP - 인터페이스 분리 원칙

  • 인터페이스 와 클래스는 분리 되어야 한다.

5) DIP - 의존관계 역전 원칙

  • 구체적인 클래스보다 상위 클래스, 인터페이스, 추상클래스와 같이 변하지 않을 가능성이 높은 클래스와
    관계를 맺어야한다. (DI)

12. 자바의 메모리 영역

  • 자바의 메모리 공간은 크게 Method 영역, Stack 영역, Heap 영역으로 구분되고, 데이터 타입에 따라
    할당된다.

1) 메소드 영역

  • 전역변수와 static 변수를 저장하며, Method영역은 프로그램 시작부터 종료까지 메모리에 남아있다.

2) 스택 영역

  • 지역변수와 매개변수 데이터 값이 저장되는 공간이다.
  • 메소드가 호출될때 메모리에 할당되고 종료되면 메모리가 해체된다.
  • LIFO (Last In First Out) 구조를 갖고 변수에 새로운 데이터가 할당되면 이전 데이터는 지워진다.

3) 힙 영역

  • new 키워드로 생성되는 객체 (인스턴스), 배열 등이 Heap 영역에 저장되며, 가비지 컬렉션에 의해
    메모리가 관리되어 진다.

4) 각 메모리 영역이 할당되는 시점

  • Method 영역 : JVM이 동작해서 클래스가 로딩 될때 생성
  • Stack 영역 : 런타임시 할당 ( 컴파일 타임 이후 실행되는 때)
  • Heap 영역 : 컴파일 타임 시 할당 (소스코드가 기계어로 변환되어 실행가능한 프로그램이 되는 과정)

13. 클래스와 객체

  • 클래스는 객체를 만들어내기 위한 설계도 혹은 틀
  • 객체를 생성하는데 사용
  • 객체는 설계도(클래스)를 기반으로 생성되며, 자신의 고유 이름과 상태, 행동을 갖는다.
  • 객체는 메모리가 할당되어 실제로 활용되는 실체는 ‘인스턴스’라고 부름

14. 생성자 (Constructor)

  • 생성자는 클래스와 같은 이름의 메소드로, 객체가 생성될 때 호출되는 메소드이다.
  • 명시적으로 생성자를 만들지 않아도 default로 만들어진다.
  • 생성자는 파라미터를 다르게하여 오버로딩 할 수 있다.

15. Wrapper Class, Boxing, UnBoxing

  • 기본 자료형 (Primitive data type)에 대한 객체 표현을 Wrapper Class라고 한다.
  • 기본 자료형 -> Wrapper class로 변환 하는 것을 Boxing이라 한다.
  • Wrapper class -> 기본 자료형으로 변환하는 것을 UnBoxing이라고 한다.

16. Synchronized

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

17. new String()과 리터럴(““)의 차이

  • new String()은 new 키워드로 새로운 객체를 생성하기 때문에 Heap 메모리 영역에 저장
  • "”는 Heap 안에 있는 String Constant Pool 영역에 저장된다.

18. String, StringBuffer, StringBuilder 차이

1) String

  • 불변의 속성을 가진다.

2) StringBuffer

  • 가변의 속성을 가진다.
  • 동기화를 지원하여 멀티 쓰레드 환경에서 주로 사용한다.

3) StringBuilder

  • 동기화를 지원하지 않아 싱글 쓰레드 환경에서 주로 사용한다.

19. String 객체가 불변인 이유

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

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

2) thread - safe

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

3) 보안 기능

  • 중요한 데이터를 문자열로 다루는 경우 강제로 해당 참조에 대한 문자열 값을 바꾸는 것이 불가능

20. 접근 제한자 (Access Modifer)

  • 변수 또는 메소드의 접근 범위를 설정해주기 위해서 사용하는 Java의 예약어
  • Public : 접근 제한 x (같은 프로젝트 내 어디서든 사용 가능)
  • protected : 해당 패키지내, 다른 패키지에서 상속받아 자손 클래스에서 접근 가능
  • (default) : 해당 패키지 내에서만 접근 가능
  • private : 해당 클래스에서만 접근 가능

21. 클래스 멤버 변수 초기화 순서

  1. static 변수 선언 부 : 클래스가 로드 될때 변수가 제일 먼저 초기화 된다.
  2. 필드 변수 선언부 : 객체가 생성될 때 생성자 block 보다 앞서 초기화 된다.
  3. 생성자 block : 객체가 생성될 때 JVM이 내부적으로 locking(thread-safe 영역)

22. static

  • static 키워드를 사용한 변수나 메소드는 클래스가 메모리에 올라갈 때 자동으로 생성된다.
  • 클래스 로딩이 끝나면 바로 사용할수 있다. 즉, 인스턴스 (객체) 생성 없이 바로 사용 가능
  • 모든 객체가 메모리를 공유한다는 특징이 있다.
  • GC 관리 영역 밖에 있기 때문에 프로그램이 종료될때까지 메모리에 값이 유지된채로 존재

1) 사용하는 이유

  • static은 자주 변하지 않는 값이나 공통으로 사용되는 값 같은 공용자원에 대한 접근에 있어서 매번
    메모리를 로딩하거나 값을 읽어들이는 것보다 ‘전역변수’같은 개념을 통해 접근하는것이 비용도
    줄이고, 효율을 높일 수 있다.
  • 인스턴스 생성 없이 바로 사용가능하기 때문에 프로그램 내에서 공통으로 사용되는 데이터들을 관리할 때
    이용

23. Inner Class 의 장점

  • 내부 클래스에서 외부 클래스의 멤버에 손쉽게 접근할 수 있다.
  • 서로 관련 있는 클래스를 논리적으로 묶어서 표현함으로써, 코드의 캡슐화를 증가시킨다.
  • 외부에서는 내부 클래스에 접근할 수 없으므로, 코드의 복잡성을 줄일 수 있다.

24. 리플렉션 (Reflection)

  • 리플렉션이란 구체적인 클래스 타입을 알지 못해도 그 클래스의 메소드, 타입, 변수들에
    접근할 수 있도록 해주는 자바 API이다.

1) 어떤 경우에 사용할까

  • 코드를 작성할 시점에 어떤 타입의 클래스를 사용할지 모르지만, 런타임 시점에 지금 실행되고 있는
    클래스를 가져와서 실행해야 하는 경우 사용된다.
  • 프레임워크나 IDE에서 이런 동적인 바인딩을 제공한다.
  • intelliJ의 자동완성 기능, 스프링의 어노테이션이 리플렉션을 이용한 기능

25. Error와 Exception의 차이

1) Error

  • 실행 중 일어날 수 있는 치명적인 오류를 말한다.
  • 컴파일 시점에 체크할 수 없고, 오류가 발생하면 프로그램은 비정상 종료 된다.
  • 예측 불가능한 UncheckedException에 속한다.

2) Exception

  • Error보다 비교적 경미한 오류이며, try-catch를 이용해 프로그램의 비정상 종료를 막을 수 있다.

26. CheckedException과 UnCheckedException의 차이

1) CheckedException

  • 실행하기 전에 예측 가능한 예외를 말하고, 반드시 예외 처리를 해야한다.
  • 대표적 ex) IOException, ClassNotFoundException 등

2) UnCheckedException

  • 실행하고 난 후에 알수 있는 예외를 말하고, 따로 예외처리를 하지 않아도 된다.
  • 대표적 ex) NullPointerException, ArrayIndexOutOfBoundException 등
  • RuntimeException은 UnCheckedException을 상속한 클래스이다.

27. 컬렉션 프레임워크

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

1) List

  • 순서가 있는 데이터의 집합
  • 데이터 중복을 허용
  • 대표적인 구현체로는 ArrayList가 있다. (Vector를 개선한 것)
  • LinkedList, Stack, Queue, Vector, ArrayList

  • 직접 new 키워드로 사용할 수 있으며, Queue 인터페이스는 LinkedList에 new 키워드를 적용해
    사용할 수 있다.

2) Set

  • 순서가 없는 데이터의 집합
  • 데이터 중복을 허용 X
  • 대표적인 구현체로 HashSet이 있고, 순서를 보장하기 위해서는 LinkedHashSet을 사용
    • (Map의 key-value 구조에서 key대신 value가 들어가 value를 key로하는 자료구조)
  • HashSet, LinkedHashSet, TreeSet

3) Map

  • 키와 같이 한쌍으로 이뤄져 있다.
  • 키를 기준으로 중복 허용 X
  • 순서가 없다.
  • key의 순서를 보장하기 위해서는 LinkedHashMap을 사용
  • HashMap, TreeMap, HashTable, Properties

28. Set과 Map의 타입이 Wrapper Class가 아닌 Object를 받을때 중복검사

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

29. Vector와 List의 차이

  • 벡터는 데이터 삽입시 원소를 밀어내지만 리스트는 노드를 연결만 하기 때문에, 삽입 삭제 부분에서
    리스트가 시간복잡도의 우위를 가진다.
  • 벡터는 랜덤부분접근이 가능하지만 리스트는 더블링크드리스트(노드가 양쪽으로 연결)로 되어있기 때문에
    랜덤 접근이 되지 않는다. 검색적인 측면에서는 벡터가 우위에 있다.
  • 벡터는 리스트와 달리 항상 동기화되는 장점이자 단점을 가지고 있다.
    • 멀티스레드 한경에서 안전하게 추가하고 삭제할 수 있지만, 단일쓰레드 환경에서도 동기화 하기 때문에
      List보다 성능이 떨어진다.

30. 제너릭

  • 제너릭은 데이터의 타입을 하나로 지정하지 않고, 사용할 때마다 범용적이고 포괄적으로 지정한다는 의미
  • 제너릭 타입을 사용함으로써 잘못된 타입이 사용될수 있는 문제를 컴파일 과정에서 제거할 수 있어
    에러를 사전에 방지할 수 있다.

31. final, finally, finalize의 차이

1) final

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

2) finally

  • try - catch와 함께 사용된다.
  • try - catch가 종료될 때 finally block이 항상 수행되기 때문에 마무리 해줘야 하는 작업이
    존재할 경우에 해당하는 코드를 작성해주는 코드 블록이다.

3) finalize

  • Object 클래스에 정의되어 있는 메소드이다.
  • GC에 의해 호출되는 메소드로 호출되서는 안되는 메소드이다.
  • GC가 발생하는 시점이 불분명하기 때문에 해당 메소드가 실행된다는 보장이 없고, fianlize() 메소드가
    오버라이딩 되어 있으면 GC가 이루어질때 바로 Garbage Collecting되지 않는다.
  • GC가 지연되면서 OOME(Out of Memory Exception)이 발생할 수 있기 때문에 finalize()
    메소드를 오버라이딩하여 구현하는 것을 권장하지 않고 있습니다.

32. 직렬화 (Serialize)

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

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

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

출처 : 슬기로운 개발생활

댓글남기기