🧑🏻💻 Java의 특징
• 객체 지향 언어로써 캡슐화, 상속, 다형성 기능을 완벽하게 지원한다.
• 운영체제에 상관없이 독립적으로 작동하여 이식성이 높다.
• Garbage Collector에 의해 메모리가 관리된다.
• 멀티 스레드를 쉽게 구현할 수 있다.
• 동적 로딩을 지원한다.
🧑🏻💻 객체 지향 프로그래밍의 특징
객체 지향 프로그래밍(Object-Oriented Programming)이란 프로그래밍에서 필요한 데이터를 추상화시켜 '객체'라는 기본 단위로 정의하고, 이 객체를 주된 관심으로 삼는 프로그래밍 방법론이다.
• 캡슐화
- 객체의 필드와 메서드를 하나로 묶는 것이며, 이를 통해 정보은닉 효과를 얻을 수 있다.
• 추상화
- 사물들의 공통적인 특징을 파악해서 하나의 개념으로 다루는 것을 뜻한다.
• 다형성
- 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 사용할 수 있도록 해준다.
• 상속성
- 상위 객체의 필드와 메서드를 하위 객체에게 물려주어 하위 객체에서 사용할 수 있도록 해준다.
🧑🏻💻 객체지향 프로그래밍의 5대 원칙(SOLID)
• 단일 책임 원칙(Single Responsiblity Principle)
- 소프트웨어의 설계 부품(클래스, 함수 등)은 하나의 책임만 가진다.
- 클래스의 기능(책임)이 많아지면 내부 함수끼리 강한 결합이 발생할 가능성이 높으므로 응집도는 높이고 결합도는 낮춰야 한다.
💡 결합도
모듈(클래스) 간의 상호 의존 정도를 뜻하며, 결합도가 낮으면 상호 의존성이 줄어들어 객체의 재사용이나 수정, 유지보수가 용이해진다.
💡 응집도
하나의 모듈 내부에 존재하는 구성 요소들의 기능적 관련성으로, 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져 재사용이나 기능의 수정, 유지보수가 용이해진다.
• 개방-폐쇄 원칙(Open-Closed Principle)
- 소프트웨어 엔티티(클래스, 모듈, 함수 등)는 확장에 대해서는 열려 있어야 하지만 변경에 대해서는 닫혀 있어야 한다.
- 이를 위해 인터페이스를 사용하기도 한다.
• 리스코프 치환 원칙(Liskov Substitution Principle)
- 자식 클래스는 부모 클래스의 기능을 대체해서 수행할 수 있어야 한다.
- 부모 클래스의 인스턴스 대신에 자식 클래스의 인스턴스를 사용해도 문제가 없어야 한다는 것을 의미한다.
• 인터페이스 분리 원칙(Interface Segregation Principle)
- 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안된다.
- 큰 덩어리의 인터페이스들을 작은 단위들로 분리시키고, 꼭 필요한 메서드들만 사용하여 내부 의존성 관계를 느슨하게 한다.
• 의존 역적 원칙(Dependency Inversion Principle)
- 상위 모듈은 하위 모듈에 종속되어서는 안 된다.
- 의존 관계를 맺을 때, 구체적인 클래스보다는 인터페이스나 추상 클래스와 관계를 맺어야 한다.
🧑🏻💻 클래스, 객체, 인스턴스
• 클래스
- 객체를 만들어 내기 위한 설계도로써 객체의 상태를 나타내는 필드(field)와 객체의 행동을 나타내는 메서드(method)로 구성된다.
• 객체
- 클래스로 구현할 모든 대상을 뜻한다.
• 인스턴스
- 객체가 메모리에 할당되어 실제 사용될 때를 지칭한다.
🧑🏻💻 JVM(Java Virtual Machine)
• JVM이란?
- Java로 개발한 프로그램을 컴파일하여 만들어지는 바이트코드를 실행시키기 위한 가상머신이다.
- Java와 OS사이에서 중개자 역할을 하여, OS의 종류와 무관하게 동일한 동작을 보장한다.
- 메모리 관리 및 Garbage Collection 수행한다.
- Stack 기반의 가상머신이다.
• JVM 구성
- 클래스 로더(Class Loader)
- 실행 엔진(Excution Engine)
- Garbage Collector
• 실행과정
1. 프로그램이 실행되면 JVM은 OS로부터 메모리를 할당받는다.
2. 컴파일러가 소스코드(.java)를 읽어 바이트코드(.class)로 변환시킨다.
3. 클래스 로더를 통해 class파일들을 JVM에 로딩시킨다.
4. 실행 엔진을 통해 로딩된 class파일들을 해석한다.
5. 해석된 바이트코드는 Runtime Data Areas에 배치된 후 실행된다.
🧑🏻💻 Garbage Collection
• 메모리 관리 기법 중의 하나로, 프로그램이 동적으로 할당했던 메모리 영역 중에서 필요 없게 된 영역을 해제한다.
• 상세내용 : https://d2.naver.com/helloworld/1329
🧑🏻💻 자바 메모리 구조
• 메서드 영역
- 클래스에 대한 정보와 클래스 변수(static variable)가 저장되는 영역이다.
• 힙 영역
- new 키워드를 통해 생성된 인스턴스의 정보가 저장되는 영역이다.
• 스택 영역
- 메서드가 호출되면, 메서드의 지역 변수와 매개변수가 저장되는 영역이다.
🧑🏻💻 접근 제한자
• public
- 모든 접근을 허용한다.
• protected
- 같은 패키지 또는 해당 부모 클래스를 상속받은 자식 클래스에서의 접근을 허용한다.
• default
- 같은 패키지 내에서의 접근을 허용한다.
• private
- 같은 클래스 내에서의 접근만 허용한다.
* 클래스에서의 접근제한자 사용
- 클래스에는 'public'과 'default'만 사용할 수 있다.
- 'default'를 사용할 경우, 다른 패키지에서 클래스를 사용할 수 없다.
🧑🏻💻 컬렉션 프레임워크(Collection Framework)
다수의 데이터를 처리할 수 있도록 표준화된 방법을 제공하는 클래스의 집합을 의미한다.
• List
순서가 있는 데이터의 집합으로 데이터의 중복을 허용한다.
- Vector : ArrayList와 구현 원리와 기능적인 측면에서 동일하며, 동기화를 지원한다.
- ArrayList : 단방향 포인터 구조로 인덱스로 접근하므로 조회할 때 유리하지만, 데이터의 삽입이나 삭제가 발생할 경우 인덱스를 조정하는 추가 작업이 필요하다.
- LinkedList : 양방향 포인터 구조로 데이터의 삽입, 삭제에 유리하다.
• Set
순서를 유지하지 않는 데이터의 집합으로 데이터의 중복을 허용하지 않는다.
- HashSet : 가장 빠르게 접근할 수 있으나 순서를 보장하지 않는다.
- TreeSet : 입력한 순서대로 값을 저장하지 않지만, 기본적으로 오름차순으로 정렬한다.
- LinkedHashSet : 입력한 순서대로 값을 저장한다.
• Map
Key와 Value의 쌍으로 이루어진 데이터 집합으로, 순서는 유지되지 않으며 Key의 중복을 허용하지 않으나 Value의 중복은 허용한다.
- TreeMap : 데이터를 이진 검색 트리(binary search tree)의 형태로 저장하므로 데이터의 삽입이나 삭제가 빠르다.
- HashMap : 가장 많이 사용되는 클래스 중 하나이며, 해시 알고리즘(hash algorithm)을 사용하여 검색 속도가 매우 빠르다.
- Hashtable : HashMap과 다르게 동기화를 보장한다.
🧑🏻💻 스트림 API
• 자바8부터 추가된 반복자이며, 컬렉션에 저장된 요소를 하나씩 참조하여 람다식으로 처리할 수 있도록 해주는 기능이다.
• Iterator와 비슷한 역할을 하지만 내부 반복자를 통해 병렬 처리가 가능하다는 장점이 있다.
🧑🏻💻 Call by Value vs Call by Reference
• Call by Value
- 값에 의한 호출을 의미한다.
- 전달받은 값을 복사하여 처리하기 때문에 전달받은 값을 변경하여도 원본의 값은 변경되지 않는다.
• Call by Reference
- 참조에 의한 호출을 의미한다.
- 전달받은 값을 직접 참조하기 때문에 전달받은 값을 변경하면 원본도 같이 변경된다.
🧑🏻💻 Overloading vs Overriding
• Overloading
- 매개변수의 개수나 자료형을 다르게 하여 같은 이름의 메서드를 사용하는 것을 뜻한다.
• Overriding
- 상속 관계에 있는 클래스 간에 같은 이름의 메서드를 재정의하는 것을 뜻한다.
🧑🏻💻 Abstract Class vs Interface
• Abstract Class
- 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스이다.
- 추상 클래스는 추상 메서드를 가지지 않아도 상관없지만 추상 메서드가 하나라도 있으면 추상 클래스가 되어야 한다.
- 필드, 생성자, 추상 메서드를 가질 수 있으며, 생성자를 가지기 때문에 객체화가 가능하다.
abstract class AbstractSample {
// Field
private int num;
// Constructor
public AbstractSample(int num) {
this.num = num;
}
// Abstract Method
public abstract void calc();
}
• Interface
- 구현 객체가 같은 동작을 한다는 것을 보장하기 위한 목적이다.
- 상수(static final)와 추상 메서드(abstract method)의 집합이다.
- 생성자를 가질 수 없어서 객체화가 불가능하다.
- 다중상속이 가능하다.
- 자바8부터 디폴트 메서드 지원한다.
interface InterfaceSample {
public static final int NUM = 10; // public static final 생략 가능. 컴파일 시에 자동 생성
public abstract void calc(); // public abstract 생략 가능. 컴파일 시에 자동 생성
}
🧑🏻💻 제네릭(Generic)
• 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법이다.
• 다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스를 컴파일할 시에 타입 체크를 할 수 있다.
🧑🏻💻 래퍼 클래스(Wrapper Class)
기본 자료타입(primitive type)을 객체로 다루기 위해서 사용하는 클래스이다.
• 박싱(Boxing)
기본 자료형을 Wrapper 클래스의 객체로 변경하는 과정을 뜻한다.
- Boxing : Integer age = new Integer(30);
- AutoBoxing : Integer age = 30;
• 언박싱(UnBoxing)
각각의 객체를 기본 자료형으로 변경하여 사용하는 과정을 뜻한다.
- UnBoxing : int age = age.intValue();
- AutoUnBoxing : Integer obj = new Integer(30); int age = obj;
🧑🏻💻 Thread
• 프로세스(Process)와 스레드(Thread)
- 프로세스란 실행 중인 프로그램을 뜻한다.
- 스레드란 프로세스 내에서 동시에 실행되는 독립적인 실행단위를 뜻한다.
• 스레드의 장점
- Context Switching이 빠르기 때문에 시스템 처리량이 증가한다.
- 프로세스 내의 Stack영역을 제외한 모든 메모리를 공유하기 때문에 통신 부담이 적어 프로그램 응답 시간이 단축된다.
• Thread 클래스와 Runnable 인터페이스
// 1. Thread 클래스를 상속받아 구현
static class MyThread1 extends Thread {
// Thread 클래스의 run()을 오버라이딩
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ingore
}
System.out.println("MyThread1 run : " + i);
}
}
}
// 2. Runnable 인터페이스를 구현
static class MyThread2 implements Runnable {
// Runnable 인터페이스의 run()을 구현
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// ingore
}
System.out.println("MyThread2 run : " + i);
}
}
}
public static void main(String[] args) {
MyThread1 t1 = new MyThread1();
Thread t2 = new Thread(new MyThread2());
t1.start();
t2.start(); // 또는 new Thread(new MyThread2()).start();
}
🧑🏻💻 Reflection
• 이미 로딩이 완료된 클래스에서 또 다른 클래스를 동적으로 로딩하여 생성자, 멤버 필드, 멤버 메서드 등을 사용하는 기법이다.
🧑🏻💻 직렬화(Serialize)와 역직렬화(Deserialize)
• 직렬화(Serialize)
- 자바 시스템 내부에서 사용되는 Object 또는 Data를 외부의 자바 시스템에서도 사용할 수 있도록 byte 형태로 데이터를 변환하는 기술을 뜻한다.
- JVM(Java Virtual Machine 이하 JVM)의 메모리에 상주(힙 또는 스택)되어 있는 객체 데이터를 바이트 형태로 변환한다.
• 역직렬화(Deserialize)
- byte로 변환된 Data를 원래대로 Object나 Data로 변환하는 기술을 뜻한다.
- 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM으로 상주시킨다.
🧑🏻💻 Checked Exception VS Unchecked Exception
• Checked Exception
- 처리여부 : 반드시 에러를 처리해야 한다.
- 확인시점 : 컴파일 단계
- 트랜잭션 처리 : ROLLBACK 하지 않는다.
- 체크예외는 컴파일러가 오류를 체크해 주기 때문에 개발자가 예외를 놓치는 실수를 막아준다. 하지만 이러한 장점 때문에 체크예외를 무분별하게 사용하게 된다면, 예외에 종속된 코드가 될 수 있다는 단점이 존재한다.
• Unchecked Exception
- 처리여부 : 명시적인 처리를 강제하지 않는다.
- 확인시점 : 실행 단계
- 트랜잭션 처리 : ROLLBACK 한다.
🧑🏻💻 Annotation
• 표준 Annotation
- @Override : 컴파일러에게 오버라이딩하는 메서드라는 것을 알린다.
- @Deprecated : 해당 메서드가 더 이상 사용되지 않음을 표시한다.
- @SuppressWarnings : 컴파일 경고를 무시하도록 한다.
- @SafeVarargs : Java7부터 지원하며, 제너릭 같은 가변인자의 매개변수를 사용할 때의 경고를 무시한다.
- @FunctionalInterface : 함수형 인터페이스라고 정의하는 어노테이션으로, 만약 메서드가 존재하지 않거나 1개 이상의 메서드(default 메서드 제외)가 존재할 경우 컴파일 오류를 발생시킨다.
• 메타 Annotation
- @Target : 어노테이션이 적용가능한 대상을 지정하는 데 사용한다.
- @Documented : 해당 어노테이션을 Javadoc에 포함시킨다.
- @Inherited : 어노테이션이 상속되도록 한다.
- @Retention : 어노테이션이 유지되는 범위를 지정한다.
- @Repeatable : Java8부터 지원하며, 연속적으로 어노테이션을 선언할 수 있게 해 준다.
참고문헌
1. tololong001.log
2. 망나니개발자 - [기술면접] CS 기술면접 질문 - 개발 언어 (7/8)
'Interview' 카테고리의 다른 글
[기술면접] Database(데이터베이스) (0) | 2023.03.29 |
---|---|
[기술면접] Web(웹 프로그래밍) (0) | 2023.03.29 |