[기초 공부] Java 정리

woodyn·2021년 5월 22일
0

기초 공부

목록 보기
8/16

Java

운영체제나 하드웨어에 의존하지 않도록 설계된 객체 지향 언어

  • Java SE: 표준적인 컴퓨팅 환경을 제공하기 위한 Standard Edition
  • Java EE: 엔터프라이즈용 기능이 추가된 확장 버전
  • JRE: Java Runtime Environment, 자바 프로그램 실행에 필요한 기본 라이브러리들
  • JDK: Java Development Kit, 자바 프로그램 개발에 필요한 툴들
    • Oracle JDK: Oracle에서 제공하는 Java SE의 구현체, 2019년 1월 부로 유료화됨
    • Open JDK: Java SE의 오픈소스 구현체
  • JVM: Java Virtual Machine, 자바 바이트 코드를 해석해서 프로그램을 실행하는 가상 머신

Call-by-value vs Call-by-reference

  • Call-by-value: 함수 인자로 변수의 값을 복사해서 전달
    • 자바에서는 원시 자료형(int, float, boolean 등)이 해당
  • Call-by-reference: 함수 인자로 변수의 레퍼런스 전달
    • 자바에서는 참조 자료형(배열, 인스턴스 등)이 해당

Access Modifier

ModifierClassPackageSubclassWorld
publicYYYY
protectedYYYN
defaultYYNN
privateYNNN

Nested class

class OuterClass {
    ...
    class InnerClass {
        ...
    }
    static class StaticNestedClass {
        ...
    }
}

집약성과 코드 가독성을 위해, 클래스 안에 클래스를 선언하는 표현

  • Inner class: 클래스 안에 non-static 클래스 선언
    • 외부 클래스의 멤버 접근 가능
  • Static nested class: 클래스 안에 static 클래스 선언
    • 외부 클래스의 멤버 접근 불가능

Lambda Expressions

하나의 메소드만을 갖는 익명 클래스를 간단히 정의하기 위한 표현

  • 메소드 내에서 실행할 내용을 인자로 넘겨야 할 때 자주 사용함
  • 외부 Scope의 변수를 final로 취급하여 참조할 수 있음 (대입 불가)
  • Method References: 존재하는 메소드를 실행하는 람다를 간단히한 표현
    • ContainingClass::staticMethodName: static 메소드 참조
    • containingObject::instanceMethodName: 인스턴스 메소드 참조
    • ContainingType::methodName: 특정 타입의 임의 객체 메소드 참조
    • ClassName::new: 클래스의 생성자 참조
  • Functional interfaces: 람다 형식을 정의한 인터페이스 (java.util.function)
    • Function: 인자와 반환 값을 가짐
    • Consumer: 인자만을 가지며 void를 반환함
    • Predicate: 인자를 가지며 boolean을 반환함
    • Supplier: 인자가 없고 반환 값만을 가짐
    • @FunctionalInterface: 인터페이스가 람다로 활용되기 위해, 단일 메소드만 갖도록 강제하는 애너테이션

Enum Types

상수를 미리 정의하기 위한 열거형 데이터 타입

  • 자바의 Enum은 클래스로 취급되어, 기본 메소드들이 제공되고 개발자가 메소드와 필드를 추가할 수 있음

Annotations

프로그램에 대한 데이터를 제공하는 메타데이터 표현

  • 표현 목적:
    • 컴파일러가 오류와 경고를 감지할 때 참고할 정보
    • 컴파일이나 배포 시 파일을 생성할 때 처리할 정보
    • 런타임 환경에서 처리할 정보
  • 클래스와 필드, 메소드, 지역 변수, 메소드 인자에 적용할 수 있음
    • 인스턴스 생성, 형변환, 인터페이스 구현, 메소드 예외 정의 표현에서도 적용 가능 (Java 8부터)
  • Repeating Annotations: 한 대상에 동일 타입의 애너테이션을 여러 개 적용할 수 있음 (Java 8부터)

Abstract Classes vs Interfaces

추상 클래스와 인터페이스는 모두 인스턴스화 할 수 없고, 구현이 없는 메소드를 정의할 수 있음

  • 추상 클래스: 생성자와 필드를 가지고, 접근이 제한된 메소드를 정의할 수 있음
    • 관련이 깊은 클래스들 간에 코드를 공유할 때 사용
  • 인터페이스: 상수 필드만 가질 수 있고, public default 메소드를 정의할 수 있음
    • 관련이 깊지 않은 클래스들의 행동을 정의해야 할 때 사용
    • 다중 상속이 필요할 때 사용

Wrapper classes


원시 타입을 감싸는 클래스

  • 사용 목적:
    • 인자가 객체 형식이어야 하는 상황 (e.g. 컬렉션 클래스)
    • 미리 정의된 상수 활용 (e.g. 최댓값, 최솟값)
    • 형식 변환을 위해 변환 메소드 호출 (e.g. 문자열 → 정수)
  • Autoboxing and Unboxing: 원시 타입과 래퍼 타입 간의 변환이 컴파일러에 의해 암시적으로 이루어짐
    • 메소드 인자로 넘겨졌을 때와 변수에 대입했을 때 발생

StringBuilder

문자열을 효율적으로 생성하는 클래스

  • 자바의 String은 성능을 위해 불변성을 가지며, 문자열을 합치는 연산은 새로운 객체를 매번 다시 만듦
    • 따라서 StringBuilder를 통해 문자 배열로 문자열을 생성하면 효율적임

Generics

파라매트릭 다형성을 Type-safe하게 다루기 위한 표현

  • Type-safe: 타입을 판별함으로써 컴파일 시에 문제를 발견할 수 있도록 함
  • 클래스와 메소드에 적용할 수 있음
  • Type Inference: 타입 인자를 명시하지 않아도, 상황에 따라 컴파일러가 추론할 수 있음
  • Type Erasure: 컴파일 시 모든 타입 인자가 상한/하한 타입 혹은 Object로 변환됨
    • 따라서 런타임 환경에서 타입 인자의 형식을 알 수 없음 (non-reifiable)

Bounded Type Parameters

<T extends B1 & B2 & B3>

인자 타입의 형식을 제한하기 위한 표현

  • extends 키워드로 상한(upper bound)을 제한함 (특정 타입을 부모로 갖도록 강제)

Wildcards


Generic 코드에서, 알 수 없는 타입을 정의하기 위한 표현

  • 무공변(invariant)한 타입 간의 상속(subtyping) 문제를 해결하기 위함

Upper Bounded Wildcards

public static double sumOfList(List<? extends Number> list) { /* ... */ }

List<Double> ld = Arrays.asList(1.2, 2.3, 3.5);
System.out.println("sum = " + sumOfList(ld));

? extends T 형식으로, 인자 타입의 상한(upper bound)을 정하기 위한 표현

  • 공변(covariant)
  • 일반적으로 입력(in) 역할의 인자에 사용

Unbounded Wildcards

public static void printList(List<?> list) {
    for (Object elem: list)
        System.out.print(elem + " ");
    System.out.println();
}

? 형식으로, 인자 타입의 상한을 Object로 정하기 위한 표현

  • 타입 인자에 의존하지 않고, Object로 다루는 코드에 사용

Lower Bounded Wildcards

public static void addNumbers(List<? super Integer> list) {
    for (int i = 1; i <= 10; i++) {
        list.add(i);
    }
}

? super S 형식으로, 인자 타입의 하한(lower bound)을 정하기 위한 표현

  • 반공변(contravariant)
  • 일반적으로 출력(out) 역할의 인자에 사용

Exceptions

메소드 내 오류를 반환하고 처리하기 위한 객체

  • 메인 로직과 오류 처리 로직을 분리시켜, 관심사의 분리를 실현함
  • Checked exception: 애플리케이션에서 예상할 수 있고, 복구 작업이 기대되는 예외 (논리적 예외 상황)
    • Catch or Specify Requirement를 항상 만족해야 함
    • 일반적인 Exception이 해당함
  • Unchecked exception: 애플리케이션에서 예상하기 어려운 예외 (외부 오류나 내부 버그 등)
    • Catch or Specify Requirement를 만족할 필요 없음
    • ErrorRuntimeException이 해당함
  • Catch or Specify Requirement: 예외를 try문으로 잡거나, 메서드 정의에 throws문으로 명시해야 함

I/O Streams

데이터가 이동하는 I/O 작업을 추상화한 클래스들 (e.g. InputStream, OutputStream)

  • Byte Streams: 바이트 단위로 데이터를 전송하는 Stream
  • Buffered Streams: 버퍼 단위로 데이터를 전송하는 Stream
    • 다른 Stream을 감싸 생성할 수 있음 (Decorator 패턴)
  • Data Streams: 원시 타입과 String을 이진 I/O 작업으로 전송하는 Stream
  • Object Streams: 객체를 이진 I/O 작업으로 전송하는 Stream
    • Serializable 인터페이스를 구현한 객체를 대상으로 함

File I/O (NIO)

파일 시스템을 추상적으로 다루기 위한 API

  • Path: 파일을 식별하는 경로 클래스
    • 기존의 legacy 클래스인 File을 대체함
  • Files: 파일과 디렉토리의 읽기와 쓰기, 조작 기능을 지원하는 클래스
  • FileSystem: 파일 시스템을 추상화한 클래스

Thread

자바의 스레드를 표현하는 클래스

  • Thread를 직접 상속하거나, Runnable 인터페이스를 구현한 클래스로 스레드를 실행할 수 있음
  • Thread.sleep(long): 일정 시간동안 스레드 대기
  • Thread.join(): 스레드가 끝날 때까지 현재 스레드 대기
  • Thread::invoke() 메소드로 스레드를 중단함
    • 인터럽트 기능을 구현하기 위해, 스레드 내부에서 InterruptedException을 catch하거나, Thread.interrupted()로 인터럽트 발생 여부를 확인해야 함

Thread State


스레드가 갖는 상태

  • NEW: 스레드가 시작하지 않은 상태
  • RUNNABLE: JVM이 스레드를 실행하는 상태
  • BLOCKED: 스레드가 잠금을 획득하기 위해 기다리는 상태
  • WATINIG: 스레드가 다른 스레드를 기다리는 상태 (wait() 이후 notify()를 기다림)
  • TIMED_WAITING: 타임아웃을 갖고 다른 스레드를 기다리는 상태
  • TERMINATED: 스레드가 종료된 상태

Synchronization

자바에서 멀티스레딩 시 동기화를 위한 방법들

  • synchronized 메소드: 해당 객체를 잠궈 원자성을 지킴 (intrinsic locking)
  • synchronized 블록: 특정 객체를 잠궈 원자성을 지킴 (intrinsic locking)
  • Immutable 객체 설계: 생성 후 불변하는 객체로 설계하면, 경쟁 상태를 예방할 수 있음
  • Lock 인스턴스: tryLock() 메소드를 통해 잠금을 시도할 수 있음
  • Concurrent collections: 동시성과 원자성을 고려한 컬렉션 클래스들
    • BlockingQueue: 가득 찬 큐에 원소를 넣을 때, 혹은 빈 큐에서 원소를 꺼낼 때 Blocking하는 큐
    • ConcurrentMap: 원자적인 메소드들을 메소드들을 제공하는 Map
  • Atomic variables: Lock 없이 단일 변수의 원자성을 지키는 클래스 (e.g. AtomicInteger, AtomicReference)
  • ThreadLocal: 스레드마다 하나의 변수를 갖도록 하는 래퍼 클래스

Executor

비동기 작업을 추상적으로 실행하기 위한 인터페이스

  • ExecutorService: Executor를 상속하며, 작업의 life cycle을 관리하는 기능을 지원함
  • ScheduledExecutorService: ExecutorService를 상속하며, 작업을 주기적으로 실행 기능을 지원함
  • Executors: Executor를 생성하는 팩토리 메소드를 지원함
    • newFixedThreadPool(int): 고정 크기의 스레드 풀 생성
    • newCachedThreadPool(): 가변 크기의 스레드 풀 생성 (단기 작업을 많이 수행할 때 활용)
    • newSingleThreadExecutor(): 단일 스레드로 작동하는 Executor 반환

Collections Framework


여러 자료 구조를 추상화된 인터페이스와 함께 제공하는 프레임워크

Collections

Set

중복을 허용하지 않고, 순서가 없는 자료 구조 (내부적으로 Map을 활용하여 구현)

  • HashSet: 해시 테이블을 통한 구현
  • TreeSet: 트리를 통해 정렬을 보장하는 구현 (SortedSet)
  • LinkedHashSet: 해시 테이블과 연결 리스트를 통한 구현 (원소의 순서를 삽입 순으로 유지)
  • EnumSet: 배열을 통해 Enum에 최적화된 구현
  • CopyOnWriteArraySet: 배열 복사로 원소 수정에 대응하는 배열을 통한 구현 (잠금 없이 thread-safe)
    • 원소가 자주 수정되지 않는 상황에 활용

List

중복을 허용하고, 순서를 갖는 자료 구조

  • ArrayList: 가변 배열을 통한 구현
  • LinkedList: 연결 리스트를 통한 구현
  • CopyOnWriteArrayList: 배열 복사로 원소 수정에 대응하는 배열을 통한 구현 (잠금 없이 thread-safe)
    • 원소가 자주 수정되지 않는 상황에 활용

Queue

FIFO 방식으로 작동하는 자료 구조

  • LinkedList: 연결 리스트를 통한 구현
  • PriorityQueue: 우선순위 큐를 통한 구현
  • BlockingQueue: push 혹은 pop이 불가능한 상황에 Blocking하는 큐 인터페이스 (큐 크기를 고정할 수 있음)
    • LinkedBlockingQueue: 연결 리스트를 통한 구현
      • 잠금을 양쪽 노드(headtail)로 분산해 처리율이 비교적 높음
    • ArrayBlockingQueue: 고정 크기 배열을 통한 구현
      • 배열을 통째로 잠궈 처리율이 비교적 낮음
      • fairness: 먼저 요청한 스레드에게 우선적으로 제공하는 기능 (optional)
    • PriorityBlockingQueue: Blocking이 적용된 우선순위 큐 구현
    • DelayQueue: 우선순위 큐로 스케줄을 관리하는 구현
    • SynchronousQueue: 원소 삽입과 제거가 서로 Blocking하는 구현

Deque

중복을 허용하고, 순서를 갖는 자료 구조

  • ArrayDeque: 가변 배열을 통한 구현
  • LinkedList: 연결 리스트를 통한 구현
  • LinkedBlockingQueue: 빈 큐에서 원소를 꺼낼 때 Blocking하는 구현

Map

key-value 쌍의 원소를 다루는 자료 구조

  • HashMap: 해시 테이블을 통한 구현 (Self-balancing BST를 통한 Separate chaining 방식)
  • TreeMap: 트리를 통해 정렬을 보장하는 구현 (SortedMap)
  • LinkedHashMap: 해시 테이블의 원소를 연결 리스트로 관리하는 구현 (원소의 순서를 삽입과 접근 순으로 유지)
  • EnumMap: 배열을 통해 Enum에 최적화된 구현
  • ConcurrenthMap: 원자적인 메소드들을 제공하는 Map 인터페이스
    • ConcurrentHashMap: 해시 테이블을 통한 구현

Collections Factory Methods

  • Collections.synchronized: 동기화가 적용된 컬렉션 래퍼 반환 (intrinsic locking)
    • VectorHashtable 등의 레거시 컬렉션에 비해, 더 완성도 있는 스레드 안정성을 보장함
  • Collections.unmodifiable: 불변성이 적용된 컬렉션 래퍼 반환
  • Collections.checked: 컬렉션을 원하는 타입으로 checked 형변환하여 반환
  • Arrays.asList: 배열로 불변 List 생성
  • Collections.nCopies: n개의 특정 원소로 이루어진 불변 컬렉션 생성
  • Collections.singleton: 1개의 특정 원소로 이루어진 불변 Set 생성
  • Collections.empty: 비어 있는 불변 컬렉션 생성

Streams

컬렉션에 대한 파이프라이닝 명령을 추상적으로 처리하는 API

  • 구체적인 처리 방식을 추상화: 메인 로직을 병렬화 등의 세부 구현과 구분함
  • 명령을 람다 인자로 정의: 컬렉션 처리 코드의 side effect를 최소화함 (코드를 이해하기 쉽게 만듬)
  • Parallelism: 멀티스레딩을 통해 명령을 병렬적으로 수행할 수 있음
  • Laziness: 명령을 한 번에 처리하여 성능을 최적화할 수 있음
  • 파이프라인 말단 명령:
    • reducing: 새로운 값을 만드는 말단 명령 (e.g. average, sum, min, max, count)
    • collecting: 존재하는 값을 수정하는 말단 명령 (e.g. 처리 결과를 담은 컬렉션 생성)

Reflection

런타임 환경에서 수행할 수 있는 매우 확장적인 기능을 제공하는 API

  • 클래스와 필드 등의 객체를 자유롭게 다루고 조작할 수 있음
  • 성능 오버헤드와 역캡슐화 등의 문제가 있으므로 무분별하게 사용해선 안 됨

JDBC

데이터베이스의 테이블에 접근하기 위한 API (Java Database Connectivity)

  • JDBC Driver: 데이터베이스와 통신하기 위해 클라이언트에 설치하는 중간 프로그램
  • DriverManager: JDBC Driver에 연결하기 위한 클래스
  • DataSource: Connection을 위해 데이터베이스를 추상화한 클래스
  • Connection: JDBC 연결을 추상화한 클래스
  • Statement: 데이터베이스에 전송되는 SQL을 추상화한 클래스
  • PreparedStatement: 효율적으로 실행하기 위해 미리 캐싱하는 Statement

DBCP

데이터베이스 커넥션 풀 (Database Connection Pool)

  • Connection의 생성 비용을 줄이기 위한 방법
    • 새로운 Connection을 생성하기 위해서는 JDBC Driver에 요청해야 함
    • 일반적인 트랜잭션은 몇 ms만에 끝나는데, 빈번히 Connection을 생성하고 닫는 일은 비효율적임
  • HikariCP
    • 여러 최적화를 통해, 다른 커넥션 풀에 비해 준수한 성능을 냄
      • 바이트 코드 최적화, FastList, ConcurrentBag
    • Spring Data JPA에서 기본적으로 사용함
profile
🦈

0개의 댓글