본문 바로가기

프로그래밍 기초

Java 기초 개념 요약 정리(2)

※ 틀린 부분이 있을 수 있으며, 피드백은 언제나 환영합니다.

서술형(답이 비어 있는 버전) 링크

https://docs.google.com/document/d/1PqHQABUqclIfIRmlGmwhG7vktxwldycCqFHjCXzGz9o/edit?usp=sharing

 

Java 기초 개념 요약 정리 2(서술형)

버전별 구분 Java : ㅡ 추가: Java : ㅡ 추가: Java : ㅡ 추가: Java : ㅡ 추가: Java : ㅡ 추가: Java : ㅡ 추가: Java : ㅡ 추가: 언어적 특성 Java는 컴파일 언어? 인터프리트 언어? 컴파일 언어(Compiled Language):

docs.google.com

 


버전별 구분

Java 8

ㄴ 추가: default 메소드, Lambda 표현식, Optional 클래스, Date and Time API, Stream API, 함수형 인터페이스
ㄴ 변경: PermGen이 Metaspace로 대체됨

 

Java 9

ㄴ 추가: Reactive Stream API

 

Java 11

ㄴ 추가: HTTP Client API

ㄴ 변경: String API 개선

 

Java 15

 추가: 텍스트 블록, ZGC, Shenandoah

 

Java 16

 추가: 레코드

 

Java 17

ㄴ 추가: sealed 클래스

 

Java 21

ㄴ 추가: 가상 메소드, 레코드 패턴, 시퀀스 컬렉션, Generational ZGC


언어적 특성

Java는 컴파일 언어? 인터프리터 언어?

컴파일 언어(Compiled Language): 컴파일러를 통해 소스 코드를 타겟 아키텍처(CPU나 가상 머신)가 즉시 실행할 수 있는 저수준 언어로 일괄 번역한 뒤에, 저수준 언어를 실행하는 언어. 번역과 실행이 분리되어 있다.

인터프리트 언어(Interpreted Language): 소스 코드를 미리 번역하여 파일을 생성하지 않고, 실행 시점에 인터프리터가 코드를 한 절 혹은 블록씩 읽어 들여 저수준 언어로 변환하면서 실행하는 언어. 번역과 실행이 동시에 이뤄진다.


Java의 특성: Java는 컴파일러가 .java 파일을 .class 파일로 컴파일하는 컴파일 언어의 특징과, .class 파일을 JVM의 인터프리터를 통해 실행하는 인터프리트 언어의 특징을 모두 갖춘 하이브리드 언어이다.

 

Java의 장단점은?

장점:
1. 플랫폼 독립성(JVM): WORA 원칙을 바탕으로 하여, 동일한 코드베이스를 여러 플랫폼에 걸쳐 실행할 수 있다.
2. 객체 지향 언어: 모든 것을 객체 단위로 생각하여 코드를 작성하므로 유지보수성과 재사용성이 높다.
3. 자동적인 메모리 관리: GC가 사용하지 않는 메모리를 해제하여 메모리 누수 위험을 덜 수 있다.

단점:
1. 느린 초기 속도: JIT 컴파일이 동반되는 인터프리트 언어이므로 C, C++ 같은 네이티브 컴파일 언어보다 초기 실행 속도가 느리다.
2. 코드의 장황함: Java는 객체 지향 언어의 공통적 특성에 더하여 명확성과 안정성을 최우선으로 고려하는 설계 방식으로 인해 다른 언어에 비해 코드가 길고 장황한 편이다.
3. 높은 메모리 소비: JVM 자체를 구동하는 데 기본적으로 메모리가 필요하다.

오류

런타임 에러 구분

ㄴ 에러(Error):

    ㅡ 프로그램 코드에 의해 수습 및 복구할 수 없으며, 개발자가 미리 예측하여 방지할 수 없는 문제.

    ㅡ Error 클래스를 상속받는다.

ㄴ 예외(Exception): 

    ㅡ 개발자가 직접 예측하여 막을 수 있는, 처리 가능하며 다소 미약한 문제.

    ㅡ Exception 클래스를 상속받는다. 

 

예외 구분

ㄴ 체크 예외(Checked Exception):

     ㅡ RuntimeException 클래스를 상속받지 않는 예외 클래스.

     ㅡ 컴파일러가 예외 처리를 제대로 하고 있는지 확인해준다.

ㄴ 언체크 예외(Unchecked Exception)

     ㅡ RuntimeException 클래스를 상속받는 예외 클래스.

     ㅡ 컴파일러가 예외 처리를 강제하지 않는다.

 

예외 처리 구문

ㄴ try-catch-finally 구문

사용 방식:
ㄴ try: 예외가 발생할 수 있는 과정.
 catch: 예외가 발생할 때 처리하는 과정.
 finally: 예외 발생과 무관하게 수행할 과정.

단점:

 try 블록과 finally 블록에서 모두 예외가 발생하면 try 블록에서 발생한 예외가 스택 트레이스에서 사라져 디버깅이 어렵다.
 이 문제를 해결하려면 finally 블록에서도 try-catch문을 다시 사용해야 하는 등 코드가 지저분해진다.
 리소스 반납을 위한 코드 또한 상당하다.

ㄴ try-with-resources 구문

사용 방식: try 괄호 안에 AutoCloseable을 구현하는 리소스 객체를 선언한다.
특징: AutoCloseable을 Closeable의 상위 인터페이스로 만들어 하위 호환성을 유지한다.
장점: 
ㄴ try 블록에서 발생한 예외를 우선 출력하고 나머지 예외는 억압된 예외로 만들어서, 예외 스택 트레이스를 보존하고 디버깅을 용이하게 한다.
ㄴ 리소스가 자동적으로 반납되도록 하여 메모리 누수를 방지하고 휴먼 오류를 줄인다.
ㄴ 리소스 반납을 위한 코드 사용을 줄여 더욱 중요한 로직에 집중할 수 있게 한다.

인터페이스

Collection

ㄴ 의미: 객체를 그 사용 목적에 적합한 자료구조로 묶어 하나로 그룹화하는 인터페이스 및 클래스의 집합.
ㄴ 종류:
List: 데이터를 순서에 따라 관리한다.
Set: 중복이 허용되지 않는 데이터를 관리한다.
Map: 데이터를 키-값 쌍으로 관리하며, 키는 중복이 허용되지 않는다.
Queue: 데이터의 입출력을 FIFO 방식으로 관리한다.
Stack: 데이터의 입출력을 LIFO 방식으로 관리한다.

 

Collections

ㄴ 의미: Collection에서 다루는 객체의 상태 관리와 제어에 필요한 공통 기능을 추상화하여 제공하는 정적 유틸리티 서비스.
ㄴ 이점: 자료구조와 관련 기능을 분리하여 독립적으로 설계하고, 자료구조를 표준화된 방식으로 다룰 수 있도록 한다.


클래스

문자열 관련 클래스

Character: UTF-16 코드 유닛을 대표하는 불변 객체.
String: 문자의 시퀀스를 대표하는 불변 객체.
StringBuilder: 버퍼 기반 가변 문자열. 동기화를 지원하지 않는다.
StringBuffer: 버퍼 기반 가변 문자열. 동기화를 지원한다.

 

ForkJoinPool

ㄴ 의미: Fork / Join Framework의 일부로 Java 7에 도입된 ExecutorService의 구현체이다.
ㄴ 활용: 가상 스레드 스케줄러로 사용되어 캐리어 스레드들을 배열 형태로 관리한다.

 

Optional Class

ㄴ 의미: nullable 값을 감싸는 래퍼 클래스.
ㄴ 사용 이유: 
    ㅡ nullable 값을 안전하게 처리할 수 있도록 하여 NPE를 방지한다.
    ㅡ null check 로직을 함수형 프로그래밍 스타일과 결합할 수 있도록 한다.

 

Wrapper Class

ㄴ 의미: 원시형 타입을 객체로서 사용할 수 있도록 하는 클래스.
ㄴ 사용 이유:
    ㅡ 원시형 타입은 제네릭 타입으로 사용할 수 없기 때문이다.
    ㅡ 컬렉션 프레임워크에서 원시형 타입을 타입 그대로 사용할 수 없기 때문이다.
    ㅡ Wrapper 클래스가 원시형 타입에 관한 유용한 메소드를 제공하기 때문이다.
ㄴ 오토박싱 및 오토언박싱

박싱: 원시형 데이터를 Wrapper 객체로 변환하는 것.
언박싱: Wrapper 객체를 원시형 데이터로 변환하는 것.
오토박싱: 박싱을 자동으로 하는 것.
오토언박싱: 언박싱을 자동으로 하는 것.

키워드

final

ㄴ 의미: 일관되게 불변성 또는 변경의 차단을 강제한다.

 

static

ㄴ 의미:

    ㅡ 메모리 관리를 위해 사용되는 키워드이며 멤버가 클래스의 인스턴스라기보다는 클래스 그 자체에 속한다는 것을 가리킨다. 
    ㅡ static 멤버는 클래스의 모든 인스턴스에 의해 공유되며 클래스의 인스턴스를 생성하는 일 없이 접근할 수 있다.


평가 전략

1. Pass by value

ㄴ 함수는 원본 변수 값의 복사본을 받는다.
ㄴ 함수 안에서의 매개변수의 변화는 원본 변수에 영향을 미치지 않는다.

2. Pass by reference

ㄴ 함수는 원본 변수로의 직접적인 참조를 받는다.
ㄴ 함수 안에서의 매개변수의 변화는 원본 변수에도 영향을 미친다.

3. Pass by reference value

ㄴ 함수는 원본 객체로의 "참조"의 복사본을 받는다.
ㄴ 참조를 통해 원본 변수에서와 같은 객체에 접근할 수 있으므로 객체에 대한 변화는 함수 외부에서도 가시적이지만, 매개변수에 새로운 객체를 재할당하는 것은 원본 변수의 객체로의 참조를 바꾸지 않는다.


API

Reflection API

ㄴ 의미: 컴파일 타임에 그들의 이름을 아는 일 없이 런타임에 클래스, 메소드, 필드, 그리고 생성자를 조사하고 조정하기 위해 Java 1.1에 도입된 API.
ㄴ 요점: 성능 오버헤드와 타입 안전성 소실로 인해 아주 조금만 사용해야 한다.

Stream API

ㄴ 의미: 배열 또는 컬렉션을 함수형 스타일로 처리하기 위해 Java 8에 도입된 API.
ㄴ 요점: 데이터를 저장하는 객체와 데이터를 처리하는 스트림을 분리함으로써 선언적이고 효율적인 데이터 처리 방식을 제공한다.


기초적인 기능 & 기술

바인딩(Binding)

ㄴ 의미:

    ㅡ 식별자 또는 이름이 어느 실제 대상을 가리키는지를 결정하고, 이 둘 간에 연결하는 과정.

ㄴ 바인딩 과정에서의 필수적 속성:
    ㅡ 이름, 자료형, 메모리 주소, 영역, 수명

ㄴ 바인딩 과정에서의 선택적 속성:

    ㅡ 값

ㄴ 유형:

정적 바인딩(Static Binding)
ㄴ 의미: 변수 및 함수가 컴파일 타임에 바인딩되는 것.
ㄴ 특징: 결정이 빠르고 효율적이다.
ㄴ 예시: 정적 메소드, private 메소드, final 메소드

동적 바인딩(Dynamic Binding)
ㄴ 의미: 변수 및 함수가 런타임에 바인딩되는 것.
ㄴ 특징: 다형성을 가능하게 한다.
ㄴ 예시: 인스턴스 메소드

상속(Inheritance)

ㄴ 의미: 타입의 계층 구조를 형성함으로써 행위에 대한 계약을 준수하면서도 기능을 확장하거나 재정의할 수 있도록 하는 방식이다. 상속 관계는 IS-A 관계라고도 한다.

ㄴ 활용: 주로 프레임워크 기능을 확장할 때와 같이 엄격한 계층 구조가 필요할 때 사용한다.

구현(Implementation)

ㄴ 의미: 부모 인터페이스 또는 추상 클래스에서의 계약을 자식 클래스에서 실체화함으로써 다형성을 확보하는 방식이다. 구현 관계는 CAN-DO 관계라고도 한다.

ㄴ 활용: Java Collections Framework와 같이 다수의 클래스를 동일한 인터페이스로 다루고자 할 때 사용한다.

 

위임(Delegation)

ㄴ 의미: 기능에 대한 요청을 다른 객체가 대신 처리하도록 하여 기능을 재사용하면서도 기능 구성의 유연성을 확보할 수 있도록 하는 방식이다. 위임 관계는 HAS-A 관계라고도 한다.

ㄴ 활용: 전략 패턴, 데코레이터 패턴 등 다양한 디자인 패턴에서 사용한다.


오버로딩(Overloading)

ㄴ 의미: 동일한 이름의 메소드를 매개변수의 타입이나 개수를 다르게 하여 여러 개 정의하는 것. 정적 바인딩을 사용한다.
ㄴ 이점: 다양한 입력 데이터 형식에 대해 동일한 기능을 제공하여 편의성을 높인다.
ㄴ 예시: System.out.println()

오버라이딩(Overriding)

ㄴ 의미: 상속 관계에 있는 하위 클래스가 상위 클래스에서 정의한 메소드를 재정의하는 것. 동적 바인딩을 사용한다.
ㄴ 이점: 상위 클래스에서의 동작을 확장하거나 구체화하여, 계층 구조의 용이성을 높인다.
ㄴ 예시: equals(), hashCode()


직렬화(Serialization)

ㄴ 의미: Java 시스템에서 사용되는 객체를 외부의 Java 시스템에서도 사용할 수 있도록 바이트 스트림과 같은 연속적인 형태로 변환하는 기술.

역직렬화(Deserialization)

ㄴ 의미: 직렬화되어 연속적인 형태로 변환된 데이터를 다시 객체로 변환하는 기술.


null을 안전하게 다루는 방법

ㄴ 방법:

1. if문에서 직접 null을 처리하는 방법
ㄴ 단순하고 직관적이며, 코드 실행 성능이 더 빠름
ㄴ NPE 위험이 상존하게 되며, null check를 누락할 가능성이 있음

2. Optional 클래스를 활용하는 방법
ㄴ nullable 상태를 명시적으로 표현할 수 있고, 이를 통해 NPE가 일어날 가능성을 감소시킬 수 있음
ㄴ 경미한 수준의 시간적, 공간적 성능 오버헤드가 있음

3. 서드 파티 라이브러리를 활용하는 방법
ㄴ Apache Commons Lang 3, Google Guava 등의 라이브러리도 null check 로직을 추상화하거나 간소화하여 코드의 가독성을 높이고 NPE 발생 가능성을 줄임

 

'프로그래밍 기초' 카테고리의 다른 글

아키텍처 기초 개념 요약 정리  (0) 2025.12.09
JVM 기초 개념 요약 정리  (1) 2025.12.08
Java 기초 개념 요약 정리(1)  (0) 2025.12.08