자바 버전들의 이해 및 특징

박종현·2022년 12월 11일

자바(Java) 기본

목록 보기
7/8

Java Programming for Complete Beginners - in28Minutes Official 강의중 정리내용입니다.

자바 버전들의 이해

Since Java SE9

Modularization

Java 9는 공식적으로 Java Platform Module System (JPMS) 또는 줄여서 '모듈'이라고 알려진 새로운 수준의 추상화를 도입한다.

프로젝트 Jigsaw(JPMS = Java Platform Module System)의 일환으로 모든 Java Platform API는 별도의 모듈들로 쪼개졌다

⇒ 애플리케이션에서 필요한(실제로 사용할) 모듈들만 명시할 수 있게(가질 수 있게) 되었다.

JPMS가 없는 Java 9 이전에는 모든 Java Platform API들을 애플리케이션에 패키징해야 했기 때문에 애플리케이션의 크기가 불필요하게 커지는 문제가 있었다.

Since Java SE10

Collection copyOf()

  • copyOf() 메서드의 경우 원본 객체와의 주소 공유도 끊어주고, unmodifiable 로 만들어서 반환한다. ⇒ 리스트에 추가하거나 수정, 삭제등이 불가하다
  • 컬렉션 내 가지고 있는 객체들의 주소는 공유된다

Local Variable Type Inference

타입추론은 말그대로 개발자가 변수의 타입을 명시적으로 적어주지 않고도, 컴파일러가 알아서 이 변수의 타입을 대입된 리터럴로 추론하는 것이다.

자바에서도 var 키워드를 통해 초기화 값이 있는 지역변수(Local Variable)의 타입 추론이 가능하다

  • var는 멤버변수, 또는 메소드의 파라미터, 리턴 타입으로 사용이 불가능
  • 위에서 키워드라고 설명했지만 var 은 어떠한 타입도 아니고 예약어가 아니다

    가령 int var = 3 과 같이 사용될 수 있는 것

  • 컴파일 시점에 타입이 결정된다.
  • Var타입 변수에는 null 값이 들어갈 수 없다.

Since Java SE11

Predicate Interface Static not method

  • argument를 받아 boolean 값을 반환하는 함수형 인터페이스
  • 인터페이스 내 정적메소드가 있고 test(T t) 를 구현하여 arguments를 검증한다.
@FunctionalInterface
public interface Predicate<T> {
    // 주어진 arguments를 검증하도록 구현
    boolean test(T t);

    // 다른 Predicate와 연결하는 역할 (&&)
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    // test()의 반대 결과 반환 (ex: true -> false)
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    // 다른 Predicate와 연결하는 역할 (||)
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    // 동일한지 체크
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }

    @SuppressWarnings("unchecked")
    static <T> Predicate<T> not(Predicate<? super T> target) {
        Objects.requireNonNull(target);
        return (Predicate<T>)target.negate();
    }
}

String Utility 추가

Since Java SE14

New Switch Expression

  • Tranditional Switch Expression
    • C, C++에서 사용하는 형태의 Switch 형식을 따른다.
    • 불필요한 반복코드 존재한다.
    • 다수의 case와 break가 존재한다.
    • 개발자의 실수로 break를 누락할 경우 다음 분기로 넘어가게 됨.
  • New Switch Expression
    • Switch 내에서 라벨이 일치하는 경우, case -> A와 같은 형식으로 표현이 가능하다.
    • 단일 수행 또는 블록 수행이 가능하다.
    • 값을 리턴할 경우 default 문장이 반드시 있어야 한다.
    • Switch 블록 내에서 계산된 값을 반환하기 위해 yeild라는 키워드를 사용한다
      • 여러문장으로 case 문장을 작성하기 위해서는 {} 으로 코드 블록을 정의한다

      • 블록내의 로직 결과로 값을 리턴하기 위해 yield 키워드를 사용한다

        int i = switch (day) {
            case MONDAY  -> 0;
            case TUESDAY -> 1;
            default      -> {
                int k = day.toString().length();
                int result = anyMethod(k);
                yield result;
            }
        };
    • 여러 조건을 쉼표로 구분하여 한 라인으로 처리할 수 있음.
      int numLetters = switch (day) {
          case MONDAY, FRIDAY, SUNDAY -> 6;
          case TUESDAY                -> 7;
          case THURSDAY, SATURDAY     -> 8;
          case WEDNESDAY              -> 9;
          default -> 0;
      };

Since Java SE15

Text Block 문법 추가

Reference) https://docs.oracle.com/javase/jp/15/text-blocks/index.html

Since Java SE16

Record 추가

  • 불변(immutable) 데이터를 생성할 수 있도록 하는 새로운 유형의 클래스
  • 객체 지향의 사상에 맞게 데이터를 간결하게 표현하기 위한 방법을 제공
  • 개발자가 동작을 확장하는 것보다 불변 데이터를 모델링하는데 집중하도록 함
  • 데이터 지향 메소드를 자동으로 구현

Record 구조

record Point(int x, int y) { }
  • class 선언 시 들어가는 class 대신 record를 사용
  • RecordName(Header) {Body} 구조
    • header에 나열되는 필드 ⇒ 컴포넌트
    • 컴파일 시점에 헤더를 통해 내부 필드를 추론한다
    • header에서 자동으로 파생되는 모든 member는 명시적으로 선언할 수 있다.
    • getter 사용시 getField() 형태가 아닌 field() 형태로 필드명만 사용하면 된다
      record Point(int x, int y) { 
          // Implicitly declared fields
          private final int x;
          private final int y;
      
          // Other implicit declarations elided ...
      
          // Implicitly declared canonical constructor
          Point(int x, int y) {
              this.x = x;
              this.y = y;
          }
      }

Record 특징

  • 레코드는 불변 객체로 abstract로 선언할 수 없으며 암시적으로 final로 선언된다
    • 한 번 값이 정해지면 setter를 통해 값을 변경할 수 없다
    • 확장 가능한 동작이 아닌 불변 데이터를 모델링 하는데 집중할 수 있도록 함
  • equals와 accessor 같은 data 기반 method를 자동으로 구현
  • record 내 각 필드(헤더에 나열한 컴포넌트)는 private final로 정의된다.
  • 별도의 생성자를 선언하지 않으면 argument에 모든 private field를 할당하는 표준 constructor가 자동으로 제공된다.
  • 다른 클래스를 상속 받을 수 없다
  • 인터페이스로는 구현 가능
  • 레코드 내부에 멤버 변수(인스턴스 필드)를 선언할 수 없다. (단 static 변수는 생성이 가능) ⇒ 헤더에서 정의한 멤버만을 record에서 관리하기 위함
  • 위의 4가지 주요 특징을 제외하고는 자바의 클래스 개발과 동일하게 사용할 수 있다.
    • new 키워드를 통해 객체화 가능
    • static 메소드, static 필드 선언 가능
    • 중첩 클래스 사용 가능 및 제너릭 타입으로 지정 가능
  • record의 body 부분은 자동으로 생성된 메소드 혹은 새로운 메소드를 추가로 작성할 수 있다

##

컴팩트 생성자

  • 클래스 생성자와 달리 생성자 매개 변수를 받는 부분이 사라진 형태
  • 컴팩트 생성자 내부에서는 인스턴스 필드에 접근할 수 없다.
record Range(int lo, int hi) {
    Range {
        if (lo > hi)  // referring here to the implicit constructor parameters
            throw new IllegalArgumentException(String.format("(%d,%d)", lo, hi));
    }
}

0개의 댓글