기타/면접 준비

자바 백엔드 기술 면접 질문 준비

coding1842 2024. 6. 29. 21:08
객체 지향 프로그래밍

● 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법

장점
● 코드 재상용이 용이 : 남이 만든 클래스를 가져와 이용가능, 상속을 통해 확장해서 사용 가능
● 유지보수 쉬움 : 클래스 내부에 멤버 변수 또는 메서드 해당 부분만 수정하면 됨
● 대형 프로젝트에 적합 : 클래스 단위로 모듈화시켜 개발 가능하므로 여러 명, 여러 회사에서 프로젝트 개발시 업무 분담 쉬움

단점
● 처리 속도가 상대적으로 느림
● 객체가 많으면 용량이 커질 수 있음
● 설계시 많은시간과 노력이 필요 

 

객체지향 프로그래밍 특징

● 캡슐화 : 기능과 특성의 모음을 클래스라는 캡슐에 분류해서 넣는것이 캡슐화, 객체의 정보 또는 기능을 접근제어자를 통해  객체에 접근, 코드의 수정할 때 영향 범위를 예측할 수 있습니다. 관련된 기능과 특성을 한 곳에 모으로 분류하기때문에 객체 재활용이 원활해졌습니다.
● 상속 : 부모클래스의 속성과 기능을 그대로 이어받아 사용할 수 있게하고 기능의 일부분을 변경해야 할 경우 상속받은 자식클래스에서 해당 기능만 다시 수정(정의)하여 사용할 수 있게 하는 것
● 추상화 : 공통의 속성이나 기능을 묶어서 이름을 붙여클래스를 설계하는 것
● 다형성 : 하나의 변수명, 함수명 등이 상황에 따라 다른 의미로 해석될 수 있는 것. 오버라이딩, 오버로딩 가능

● 오버라이딩 : 상위 클래스가 가지고 있는 메소드를 상속 받을 때 자식 클래스에서 메소드를 재정의하는것
● 오버로딩 : 같은 이름의 함수를 여러개 정의하고, 매개변수의 타입과 개수를 다르게하여 매개변수에 따라 다르게 호출할 수 있게 하는 것  

 

객체 지향 설계 5대 원칙

객체지향 설계 5대원칙은 SOLID라 하며, 각 원칙의 앞글자이다
● SRP 단일 책임 원칙 (Single Responsibility Principle) : 한 클래스는 하나의 책임만 가져야 하고 그 책임을 수행하는데 집중되어 있어야 한다. 변경이 있을 때 파급 효과가 적으면(딱 하나의 클래스만 수정해도 된다면) 단일 책임 원칙을 잘 따른 것
● OCP 개방-폐쇄 원칙 (Open/Closed Principle) :  소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다. 변경시 기존 구성요소는 변경이 일어나지 않아야 한다. 기존 구성요소를 재사용 할 수 있어야 한다. 다형성을 활용해 기존의 코드를 바꾸지 않고 확장할 수 있다. 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현하는 경우는 기존 코드를 변경한 것이 아니다.
● LSP 리스코프 치환 원칙 (Liskov Substitution Principle) : 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다. 인터페이스를 구현한 구현체를 믿고 사용하려면 이 원칙이 필요. 자동차 인터페이스에 앞으로 가는 기능인 엑셀이 있다. 이걸 하위 클래스에서 엑셀을 뒤로가게 하는 기능으로도 만들 수 있다. 컴파일 오류는 발생하지 않는다. 하지만 이 인터페이스 규약에서 엑셀은 앞으로 가는 기능이기 때문에 하위 클래스에서 이 기능을 보장 해줘야 한다.
● ISP 인터페이스 분리 원칙 (Interface Segregation Principle) : 범용 인터페이스 하나보다 인터페이스 여러 개가 낫다. 큰 덩어리의 인터페이스를 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 합니다. 인터페이스를 분리하게 되면 기능이 명확해지고 대체 가능성이 높아집니다.
● DIP 의존관계 역전 원칙 (Dependency Inversion Principle) :  추상화에 의존해야지 구체화에 의존하면 안된다. 의존성 주입(DI)는 이 원칙을 따르는 방법 중 하나. 구현 클래스에 의존하지 말고 인터페이스에 의존하라. 인터페이스에 의존하게되면 구현 클래스에 대해서 몰라도 되기 때문에 유연하게 구현체를 변경할 수 있다. 구현 클래스에 의존하게 되면 변경이 어려워진다. 

 

추상 클래스와 인터페이스 차이

● 추상 클래스 : 추상 메소드를 포함하고 있는 클래스. 추상 메소드는 메소드의 내부가 구현되지 않은 메소드. 클래스 내부에 이 추상 메소드가 하나라도 있다면 클래스 앞에 abstract 키워드를 붙여서 추상 클래스로 만들어 줘야 함. 추상 메소드는 상속받은 클래스에서 반드시 구현 되어야 하기 때문에 추상 클래스에는 final 키워드를 붙일 수 없다. 추상 클래스 내부에는 일반 메소드나 변수가 존재할 수 있다. 이렇게 구현된 일반 메소드는 다른 클래스의 메소드와 똑같이 동작함. 다중상속을 할 수 없다. 하위 클래스는 오직 상속받은 추상 클래스의 기능을 이용하고 확장하는 역할.
● 인터페이스 : 모든 메소드가 추상 메소드로만 구성된 것. 상속하는 클래스에서는 인터페이스에 존재하는 모든 추상메소드를 구현해야 한다. 반드시 상속 되어야 하기 때문에 인터페이스 역시 final 키워드를 붙일 수 없다. 상속받은 클래스는 모든 메소드를 재정의 해야 함. 클래스의 인스턴스는 인터페이스를 통해 다형성을 가질 수 있다. 인터페이스는 하위 클래스에게 일종의 설계도 역할을 함. 하위 클래스는 여러개의 설계도를 가질 수 있고 각각의 설계도에 맞는 구현체를 제공할 수 있다.
● 궁극적인 차이 : 추상 클래스는 상속받은 클래스의 기능을 이용하고 확장하는 것. 인터페이스는 하위 클래스에게 일종의 설계도를 제공한다.

 

객체지향, 함수형의 차이

● 객체 중심의 설계 , 함수 중심의 설계
● 클래스 디자인과 객체들의 관계 중심 코드, 값의 연산 및 결과 도출 중심 코드
● 클래스가 일급 객체, 함수 자체가 일급 객체
● 같은 인자값에 대해 다른 결과값이 반환될 수 있음, 항상 같은 결과값 반환됨

 

자바 애플리케이션, JVM 실행 과정

● JVM (Java Virtual Machine) : 스택 기반의 가상 머신으로 Java가 OS에 구애받지 않고 재사용 가능하게 해주고 자바 바이트 코드를 실행할 수 있는 주체.

● 자바 프로그램 실행 과정
1. 프로그램이 실행되면 JVM은 OS로 부터 프로그램이 필요로 하는 메모리를 할당받는다. JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리한다.
2. 자바 컴파일러 javac가 자바 소스 코드를 읽어들여 자바 바이트코드 .class로 변환시킨다.
3. Class Loader를 통해 class 파일들을 JVM으로 로딩한다.
4. 로딩된 class 파일들은 Execution Engine을 통해 해석된다.
5. 해석된 class 파일들은 Runtime Data Area에 배치되어 실질적인 수행이 이루어지게 된다. 이 실행과정 속에서 JVM은 필요에 따라 스레드 동기화와 GC(Garbage Collection) 같은 관리 작업을 수행한다.  

 

자바 메모리 구조

● Method Area : JVM이 실행되면서 생기는 공간. class 정보, 전역변수 정보, static 변수가 저장되는 공간. Runtime Constant Pool에는 상수정보가 저장되는 공간. 모든 스레드에서 정보 공유
● Heap : new 연산자로 생성된 객체, Array와 같은 동적으로 생성된 데이터가 저장되는 공간. Heap에 저장된 데이터는 Garbage Collector가 처리하지 않는한 소멸되지 않는다. Reference Type의 데이터가 저장되는 공간. 모든 스레드에서 정보 공유
● Stack : 지역변수, 메소드의 매개변수와 같이 잠시 사용되고 필요가 없어지는 데이터가 저장되는 공간. 후입선출(Last In First Out) 나중에 들어온 데이터가 먼저 나간다. 지역변수 이지만 Reference Type일 경우에는 Heap에 저장된 데이터의 주소값을 Stack에 저장해서 사용하게 된다. 스레드마다 하나씩 존재
● PC Register : 스레드가 생성되면서 생기는 공간. 스레드가 어느 명령어를 처리하고 있는지 그 주소를 등록한다. JVM이 실행하고 있는 현재 위치를 저장하는 역할
● Native Method Stack : Java가 아닌 다른 언어 (C, C++)로 구성된 메소드 실행이 필요할 때 사용되는 공간

 

클래스 로더

클래스 로더 : 자바는 동적로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스 로드하고 링크하는 특징이 있다. 이 동적 로드를 담당하는 부분이 JVM의 클래스 로더이다. 클래스 로더는 런타임 중에 JVM의 메소드 영역에 동적으로 Java 클래스를 로드하는 역할을 한다. 클래스 로더에는 로딩, 링크, 초기화 단계로 나뉘어져 있다.

로딩
● 자바 바이트 코드(.class)를 메소드 영역에 저장

● 각 자바 바이트 코드(.class)는 JVM에 의해 메소드 영역에 다음 정보들을 저장
- 로드된 클래스를 비롯한 그의 부모 클래스의 정보
- 클래스 파일과 class, interface, enum의 관련 여부
- 변수나 메소드 등의 정보

링크
● 검증 : 읽어 들인 클래스가 자바 언어 명세 및 JVM 명세에 명시된 대로 잘 구성되어 있는지 검사
● 준비 : 클래스가 필요로 하는 메모리를 할당하고, 클래스에서 정의된 필드, 메소드, 인터페이스를 나타내는 데이터 구조를 준비
● 분석 : 심볼릭 메모리 레퍼런스를 메소드 영역에 있는 실제 레퍼런스로 교체

초기화
● 클래스 변수들을 적절한 값으로 초기화 한다. static 필드들이 설정된 값으로 초기화 한다.

 

클래스 로드 과정

● 클래스 로더는 새로운 클래스를 로드해야 할 때 다음과 같은 방식으로 로드를 수행

1. JVM의 메소드 영역에 클래스가 로드되어 있는지 확인. 로드되어 있는 경우 해당 클래스 사용
2. 메소드 영역에 클래스가 로드되어있지 않을 경우 시스템 클래스 로더에 클래스 로드를 요청
3. 시스템 클래스 로더는 확장 클래스 로더에 요청을 위임
4. 확장 클래스 로더는 부트스트랩 클래스 로더에 요청을 위임
5. 부트스트랩 클래스 로더는 부트스트랩 Classpath(JDK/JRE/LIB)에 해당 클래스가 있는지 확인. 클래스가 존재하지 않는 경우 확장 클래스 로더에게 요청을 넘김
6. 확장 클래스 로더는 확장 Classpath(JDK/JRE/LIB/EXT)에 해당 클래스가 있는지 확인. 클래스가 존재하지 않을 경우 시스템 클래스 로더에게 요청을 넘김
7. 시스템 클래스 로더는 시스템 Classpath에 해당 클래스가 있는지 확인. 클래스가 존재하지 않는 경우 ClassNotFoundException을 발생시킴

 

가비지 컬렉터, 가비지 컬렉션
 

● 가비지 컬렉터 : 메모리 관리를 담당하는 시스템 또는 프로그램의 구성요소, 메모리에서 더 이상 사용되지 않는 객체를 찾아 제거하여 메모리를 회수하는 역할을 수행
● 가비지 컬렉션 : 메모리 관리 기술 중 하나로, 가비지 컬렉터에 의해 수행하는 프로세스를 의미

가비지 컬렉션은 프로세스 자체를 얘기하고 컬렉터는 실제 역할을 수행하는 주체를 얘기한다.   

 

컬렉션 프레임워크

컬렉션 프레임워크 : 배열을 사용하다 보면 여러가지 비효율적인 문제가 생김. 가장 큰 문제점은 크기가 고정. 배열의 크기는 생성할 때 결정되며 그 크기를 넘어가게 되면 더이상 데이터를 저장할 수 없음. 또 데이터를 삭제하면 해당 인덱스의 데이터는 비어있어 메모리가 낭비되는 등 여러 문제점 발생. 자바는 배열의 문제점을 해결하기 위해 널리 알려져 있는 자료구조를 바탕으로 객체나 데이터들을 효율적으로 관리(추가, 삭제, 검색, 저장)할 수 있는 자료구조들을 만들어 놓음. 이러한 자료구조들이 있는 라이브러리를 컬렉션 프레임워크라 함. 대표적으로 List, Set, Map, Stack, Queue 등이 있음.

 

Vector, ArrayList 차이

● Vector는 한 번에 하나씩 스레드에서만 접근 가능
●  ArrayList는 동시에 여러 스레드에서 접근 가능

 

HashSet, TreeSet, LinkedHashSet 차이

● HashSet : 세트의 반복 순서를 보장하지 않거나 시간이 지나도 순서가 일정하게 유지

-> 성능이 중요하고 요소의 순서가 중요하지 않은 경우 사용
● TreeSet : 사용된 생성자에 따라 요소의 자연스러운 순서에 따라 또는 지정된 comparator에 따라 반복
-> 요소가 자연적인 순서를 사용하거나 comparator에 의해 순서화되어야 할 때
● LinkedHashSet : 요소가 집합에 삽입된 순서와 동일한 예측 가능한 반복 순서를 정의하는 모든 요소를 통해 이중 연결된 목록을실행
-> 요소의 삽입 순서를 유지해야 하는지 여부  

 

HashMap, LinkedHashMap, HashTable, TreeMap 차이

네가지 모두 키(key)에서 값(value)으로의 대응 관계가 있고 키를 기준으로 순회할 수 있음. 이 클래스들의 가장 큰 차이점은 시간 복잡도와 키가 놓이는 순서에 있음.

HashMap
● 검색과 삽입에 O(1) 시간이 소요된다.
● 키의 순서는 무작위로 섞여 있다.
● 구현은 연결리스트로 이루어진 배열로 되어 있다
● null key와 null value를 모두 허용한다

LinkedHashMap
● 검색과 삽입에 O(1) 시간이 소요된다.
● 키의 순서는 삽입한 순서대로 정렬되어 있다.
● 구현은 양방향 연결 버킷으로 구현되어 있다.

TreeMap
● 검색과 삽입에 O(log N) 시간이 소요된다.
● 키의 순서는정렬되어 있다. 즉 키는 반드시 comparable 인터페이스를 구현하고 있어야 한다.
● 구현은 레드-블랙 트리로 구현되어 있다.

HashTable
● 검색과 삽입에 O(1) 시간이 소요된다.
● 키의 순서는 무작위로 섞여 있다.
● 구현은 연결리스트로 이루어진 배열로 되어 있다.
● null key와 null value를 모두 허용하지 않는다.
● 동기화를 지원한다. (thread safe)
-> 따라서 HashTable은 멀티스레드 환경에서 동작가능하며 동기화를 지원하기 때문에 HashMap보다는 느리다. 일반적으로 별다른 이유가 없으면 HashMap을 사용하는 것이 좋다. 일반적으로 빠르고 오버헤드가 적기 때문이다.

● 삽입한 순서대로 키 정보를 얻고 싶다면 LinkedHashMap
● 정렬된 순서대로 키 정보를 얻고 싶다면 TreeMap
● 병렬 처리를 하면서 자원의 동기화를 고려해야 하는 상황이라면 HashTable   

 

Servlet 개념, 생명주기

Servlet : 자바 플랫폼에서 웹 앱을 개발할 때 사용하는 핵심기술. 서버에서 웹페이지 등을 동적으로 생성하거나 데이터 처리를 수행하기 위해 자바로 작성된 프로그램. Servlet은 JAVA코드안에 HTML태그가 삽입되어 만들어지며 확장자는 .java임.


Servlet 생명주기
1) 사용자가 url을 호출하여 컨테이너에 새로운 요청을 한다.
2) 컨테이너가 요청을 접수하여 HttpServletRequest request 객체 / HttpServletResponse response 객체를 생성
3) 접수된 url을 분석하여 해당 서블릿 객체를 생성
- 서블릿 객체가 생성되면서 서블릿에서 init() 메서드를 실행하여 Servlet 객체를 초기화함
- 사용자 요청을 처리하기 위해 스레드를 생성
4) service(request, response) 메서드가 호출되어request 타입을 분석하여 타입에 따라 적절한 메서드를 호출
- GET 방식이라면 doGet()으로, POST 방식이라면 doPost()를 호출
5) 응답을 클라이언트에 전송
6) was가 종료되면서 destory() 메서드 실행, 생성된 스레드를 소멸시킴

간략하게
1. 요청 시 서블릿 객체 생성
2. 서버는 init() 메서드를 호출하여 서블릿을 초기화
3. service() 메서드를 호출해서 서블릿이 브라우저의 요청을 처리
4. service() 메서드는 특정 HTTP요청(GET, POST 등)을 처리하는 메서드
- doGet(), doPost() 등 호출
5. 서버는 destory() 메서드를 호출하여 서블릿을 제거

 

JSP

HTML을 코딩하기 너무 어렵고 불편해서 HTML내부에JAVA코드를 삽입하는 형식이 JSP입니다. 다시말해 서블릿의 단점을 보완해서 만든 서블릿 기반의 스트립트 기술입니다. 서블릿을 이용해서 웹프로그래밍을 할 수는 있지만 자바에 대한 지식이 필요하고 화면 인터페이스 구성에 너무 많은 코드들이 필요하는 등 비효율적인 측면들이 많습니다. 때문에서블릿을 작성하지 않고도 웹프로그래밍을 쉽게 할 수 있게 해주는 기술이 바로 JSP(Java Server Page) 입니다.    

 

Servlet, JSP 차이 비교

Servlet
● 자바코드로 구현하고 컴파일, 배포한다.
● HTML 태크로 문자열("")스크림으로 처리해야한다.
● 자바에 대한 깊은 이해도를 요구한다.
● 코드가 수정되면다시 컴파일하고 배포해야 한다.

JSP
● 키워드가 태그화 되어있어 서블릿에 비해 배우기 쉽다.
● 자바코드를 <%%> 태그 안에서 처리한다.
● 자바에 대한 깊은 이해도가 필요하지 않다.

Servlet과 JSP는 각자 잘하는 역할을 담당해서 웹 어플리케이션을 구성합니다. JSP는 사용자에게 결과를 보여주는 역할을 담당하고 Servlet은 클라이언트의 요청을 받아 분석하고 비즈니스 층과 통신해 처리한 후 그 결과를 다시 클라이언트에게 응답하는 컨트롤러 층을 담당합니다. 클라이언트는 서블릿에 요청을 하고 서블릿은 이를 처리한 후 JSP를 이용해서 클라이언트에게 응답하는 구조입니다. MVC패턴에서 View는 JSP, Controller는 Servlet을 사용합니다.

 

지역변수, 전역변수, 정적변수 차이

지역변수(stack 영역)
● 지역안에서 선언된 변수

● 그 영역의 닫는 중괄호 } 를 만났을 때, 메모리에서 해제된다.
● 사용자가 직접 초기화 해야한다.
● 다른 영역에서 접근할 수 없기 때문에 보안성이 뛰어나다.

전역변수(data 영역)
● 클래스 영역 안에 있고 전체 영역에서 사용가능한 변수
● 클래스 영역 외의 어떠한 영역에도 포함되어 있지 않다.
● new를 만났을 때 초기화 된다.
● 프로그램 종료시 메모리에서 해제된다.
● 다른 영역에서도 접근 할 수 있기 때문에 보안성이 상대적으로 낮다.

static변수(data 영역)
● 컴파일 하게 되면 가장 먼저 메모리에 올라가고 어떠한 경우에도 초기화가 되지 않는다.
● 단 프로그램 종료시 메모리에서 해제 된다.
● 메모리에 고정되기 때문에 남용시 메모리 혹은 프로그램 실행 속도에 악영향을 준다.

 

접근제어자 설명

public
● public이 붙은 변수나 메서드는 같은 프로젝트 안에서 사용 가능합니다.

default
● 접근제어자가 아무것도 붙지 않은 변수나 메서드는 default 상태로 같은 패키지 안에서만 사용 가능합니다.

protected
● protected가 붙은 변수나 메서드는 다른 패키지에서는 사용이 불가능합니다. 다만 상속 관계일 때는 다른 클래스에서 사용 가능합니다.

private
● private가 붙은 변수나 메서드는 같은 클래스 내에서만 사용 가능합니다.

 

접근제어자를 사용하는 이유

보안때문에 사용. 웹사이트에서 아이디와 비밀번호 같은 중요한 정보를 public 변수에 저장한다면 아무데서나 직접적으로 접근하여 그 값을 변경할 수 있기 때문에 노출되기 쉽다. 이런 중요한 변수들은 대대분 private를 붙여준다. 여러 사람들과 함께 프로그램을 만들다 보면 다른 사람이 내가 만든 중요한 변수나 메서드를 무분별하게 사용하여 값을 변경할 수 있는데 이를 막기 위해 상황에 맞는 접근제어자를 사용합니다.

 

직렬화(Serialize)

Java 직렬화
● 자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록 바이트(byte) 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 역질렬화를 포함
● 시스템적으로 JVM의 Runtime Data Area(Heap 또는 Stack영역)에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술로 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시키는 형태를 말하기도 함

 

Wrapper Class

자바의 자료형은 크게 기본 타입(primitive type)과 참조 타입(reference type)으로 나누어진다. 대표적으로 기본 타입은 char, int, float, double, boolean 등이 있고 참조 타입은 class, interface 등이 있다. 기본타입의 데이터를 객체로 표현할 때 기본 자료타입(primitive type)을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스(wrapper class)라고 한다. 자바는 모든 기본타입(privitive type)은 값을 갖는 객체를 생성할 수 있다. 이런 객체를 포장 객체라고도 하는데 그 이유는 기본 타입의 값을 내부에 두고 포장하기 때문이다. 래퍼 클래스로 감싸고 있는 기본 타입 값은 외부에서 변경할 수 없다. 값을 변경하고 싶다면 새로운 포장 객체를 만들어야 한다.
기본타입(primitive type) 래퍼클래스(wrapper class)
byte Byte
char Character
int Integer
float Float
double Double
boolean Boolean
long Long
short Short

 

== 연산자와 String 클래스의 equals() 메소드의 차이

==연산자는 비교하고자 하는 두개의 대상의 주소값을 비교, String클래스의 equals() 메소드는 비교하고자 하는 두개의 대상의 값 자체를 비교.

int, char형 등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용됨. 하지만 String은 일반적인 타입이 아니라 클래스임. 클래스는 기본적으로 Call by Reference형태로 생성 시 주소값이 부여됨. String타입을 선언했을 때는 같은 값을 부여하더라도 서로간의 주소값이 다를 수 있음.

 

제네릭(Generic)

데이터 형식에 의존하지 않고 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법
어떤 자료구조를 만들어 배포하려고 할 때 String 타입, Integer 타입 등 많은 타입을 지원하고 싶을 때 String에 대한 클래스 Integer에 대한 클래스 등 하나하나 타입에 따라 만드는 비효율적인 방법보다 효율적으로 제네릭을 사용.
제네릭(Generic)은 클래스 내부에서 지정하는 것이 아니라 외부에서 사용자에 의해 지정되는 것을 의미함. 특정(Specific) 타입을 미리 지정해 주는 것이 아니라 필요에 의해 지정할 수 있도록 하는 일반(Generic) 타입이다.

제네릭(Generic)의 장점

1. 제네릭을 사용하면 잘못된 타입이 들어올 수 있는 것을 컴파일 단계에서 방지할 수 있다.

2. 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환해줄 필요가 없다. 관리하기 편하다.
3. 비슷한 기능을 지원하는 경우 코드의 재사용성이 높아진다.

 

final

final은 한 번만 할당할 수 있는 엔티티(Entity)를 정의할 때 사용합니다. 메서드를 final로 선언하면 상속받은 클래스에서 오버라이딩이 불가능하게 되고 구현한 코드의 변경을 원하지 않을 때 사용함. side-effect가 있으면 안 되는 ㅏㅈ바 코어 라이브러리에서 final로 선언된 부분을 많이 찾을 수 있음.

 

자바 버전 특징

자바 8 특징
● 람다 표현식 : 함수형 프로그래밍을 자바에서 사용 가능하게 해줌. 별도로 함수를 구현하지 않고 화살표를 사용해서 간단히 한 줄로 함수를 만들 수 있음.
● Stream : 반복문을 처리하는 방법 중 하나로 병렬처리가 가능함. 스레드 풀에 가용할 수 있는 스레드들을 가져와서 사용함으로 반복문 처리 속도가 빠름.
● interface의 default라는 메서드를 구현할 수 있음 : 기존에는 공통적인 함수라도 인터페이스의 구현체들은 똑같은 것을 각각 다 따로 구현해줘야 했는데 default가 생김으로 인터페이스안에 공통적으로 사용하는 함수를 미리 정의할 수 있게 됨.
● Optional : Null이 될 수 있는 객체를 감싸는 래퍼클래스. 객체에 Null이 대입되어 발생되는 오류들이 많아서 이를 좀 더 안전하게 처리하기 위해 만들어짐.

자바 11 특징
● String, File 클래스에 몇가지 메서드 추가
● 람다표현식에 var 키워드 사용 가능하도록 기능 추가
● Http Client 추가 : 기존에는 아파치 라이브러리를 사용했는데 자바 11 부터는 자바 표준 Http Client API가 생겼고 성능이 이전 것보다 개선됨.