티스토리 뷰

Java version에 따라 추가된 새로운 기능에 대한 좋은 자료가 있어서 퍼왔다. 빨간색으로 강조한건 아래 예제도 있다. 

사용 예제도 이해하기 쉽게 써놓은 글이 있어서 퍼왔다. 

버전
(Preview-Production)
기능 종류 설명
8 Lambda Expression 및
Method Reference 도입
Language anonymous inner class 표현 간략화 (함수형 표현)
인자로 method reference를 전달 (함수형 표현)
8 Collections & Streams Language Collections에서 Streams API를 사용하여, 이전의 반복문이 아닌 함수형 구현
8 Interface Default Method 도입 Language interface 내부에서 default 메서드를 선언할 수 있다.
8 Optional Class 도입 Language Optional Class를 이용하여 NullPointerException이 발생하는 것을 방지해 준다.
9 Module System & Jigsaw Project Platform Java 플랫폼 간소화 및 모듈화를 통해, 성능 및 사이즈 향상, 유연한 이미지 구성이 가능하도록 만들어 준다.
9 jlink Tool 모듈들을 조합하여 사용자 정의 런타임 이미지를 구성하는 도구
9 Jshell - 대화형 커맨드 라인 툴(REPL) 도입 Tool Java 프로그래밍 학습과 Java 코드 프로토타이핑을 위한 대화식 도구
9 Collection Factory Method 도입 Core Libraries 편리하게 콜렉션과 맵의 인스턴스를 생성 할 수 있는 새로운 정적 팩토리 메서드를 제공
9 Streams 기능 추가 Core Libraries Stream 기능에 takeWhile,dropWhile,iterate 등의 추가 메서드 제공
9 Interface Private Method 도입 Language interface 메서드들을 default, static이 아닌, private로 지정하여, interface에 대한 보안을 향상시킨다
9 Linux/AArch64 지원 Platform 리눅스 ARM64 지원
9-11 새로운 HTTPClient API Core Libraries 기존에 제공된 낮은 수준의 API를 HTTP/2, WebSocket 기반의 최신 기능들로 업그레이드
10- Java 기반의 JIT 컴파일러 (Graal VM) Performance 새로운 JIT 컴파일러 탑재
10 var - 지역변수 type 추론 Keyword 도입 Language 변수의 타입을 컴파일러가 결정해 주는 var 변수 타입을 선언할 수 있다
10 어플리케이션 CDS(Class Data Sharing) 공유 Performance 어플리케이션 시작 속도 및 설치 공간을 개선하기 위해 기존 클래스 데이터 공유("CDS") 기능을 확장하여 애플리케이션 클래스를 공유 아카이브에 배치
10,8u191 Docker 컨테이너 지원 Platform Docker 환경에 맞게 수정
11 String & Files 에 새로운 Method 추가 Language String에 strip, isBlack, lines 등, Files에 readString 등 Method 추가
11 Lambda 인수로 var 사용 가능 Language 람다 인수 선언시 var 키워드 사용 가능
11 소스 파일 실행 (javac 컴파일 불필요) Platform Java 소스 파일을 컴파일 하지 않고 스크립트로 실행
11-15 ZGC - 차세대 Garbage Collector Performance 새로운 Garbage Collector 도입
12-14 개선된 switch문 표현방식 지원 Language switch문에서 "->" 사용으로, 코딩 간소화
12 Default CDS 저장장소 Performance 어플리케이션 간에 공유되는 CDS (Class Data Sharing)에 대한 파일이 classes.jsa로 기본 저장
12 Unicode 11 지원 internalization  
12-15 Shenandoah: 멈춤 적은 가비지 컬렉터 Performance 멈춤 시간 적은 가비지 컬렉터 도입
12 G1에서 사용하지 않는 메모리 빠른 반환 Performance G1 가비지 컬렉터에서 사용하지 않는 힙 메모리를 빠르게 반환한다
13-15 Text Block 기능 도입 Language String에서 여러 줄의 문자열을 한번에 입력할 수 있다
13 Unicode 12.1 지원 internalization  
13 yield 예약어 사용 Language switch문에서 yield (switch의 return) 사용
14 instanceof 패턴매칭 - 이후 캐스팅 불필요 Language instanceof 객체에 대한 캐스팅이 필요 없어졌습니다.
14 NullPointerException 기능 추가 Platform NullPointerExceptions이 발생할 때, Exception 메세지에 어떤 변수가 null 인지 알려줍니다.
14-16 패키징 툴인 jpackage 도구 제공 tool Java 응용 프로그램을 해당 OS(Windows, Linux, Mac)에 맞게, 실행에 필요한 모든 라이브러리와 함께 패키징하는 jpackage 도구제공
14-16 Record Class 도입 Language data를 다루는 record 클래스를 이용해서 간단하게 새로운 데이터 클래스 생성
15- Sealed Class 도입 Language sealed 키워드를 이용하여 클래스의 상속을 제한할 수 있다.
16 Unix 도메인 소켓 채널 core libraries 소켓 채널 API에 유닉스 플랫폼과 Windows에서 흔히 볼 수 있는 유닉스 도메인 소켓의 모든 기능에 대한 지원을 추가
16 Windows/AArch64 지원 Platform Windows ARM64 지원
16 Alpine Linux 지원 Platform 작은 용량의 Alpine Linux 지원
16- 외부 링커 API Language JNI(Java Native Interface)의 교체로, 네이티브 코드에 접근할 수 있는 API 제공

 참고 : https://blogs.oracle.com/javakr/post/java8-16

 

 

Optional 클래스

널 포인터 예외는 가장 전통적인 오류 가운데 하나다. 익숙한 문제지만 방지하기가 쉽지 않기도 하다. 그러나 자바 8에서 처음 소개되어 자바 10에서 더 개선된 Optional 클래스를 사용하면 더 이상 골칫거리가 아니다.

기본적으로 Optional 클래스는 변수를 래핑한 다음 래퍼의 메서드를 사용해서 널을 더 간편히 다룰 수 있게 해준다.
 
예시 1에는 흔한 널 포인터 오류의 예가 나와 있다. 클래스 레퍼런스인 foo가 널이고, 여기서 메서드인 foo.getName()이 액세스된다.

예시 1. Optional이 없는 널 포인터

public class MyClass {
    public static void main(String args[]) {
      InnerClass foo = null;
      System.out.println("foo = " + foo.getName());
    }
}
class InnerClass {
  String name = "";
  public String getName(){
      return this.name;
  }
}

Optional은 필요에 따라 이 같은 상황에 대처하기 위한 여러 접근 방법을 제공한다. isPresent() 메서드를 사용하면 조건 확인이 가능하다(if-check). 그러나 이 경우 상당히 장황하게 될 수 있다. Optional에는 실용적인 처리를 위한 메서드도 있다. 예시 2는 ifPresent()(isPresent()와는 한 글자 차이)를 사용해서 값이 있는 경우에만 출력 코드를 실행하는 방법을 보여준다.

예시 2. 값이 있는 경우에만 코드 실행

import java.util.Optional;
public class MyClass {
    public static void main(String args[]) {
      InnerClass foo = null; //new InnerClass("Test");
      Optional fooWrapper = Optional.ofNullable(foo);
      fooWrapper.ifPresent(x -> System.out.println("foo = " + x.getName()));
      //System.out.println("foo = " + fooWrapper.orElseThrow());
    }
}
class InnerClass {
  String name = "";
  public InnerClass(String name){
      this.name = name;
  }
  public String getName(){
      return this.name;
  }
}

 : Optional을 사용할 때 orElse() 메서드를 사용하여 메서드 호출을 통해 기본값을 제공한다면 그 대신 orElseGet()을 사용해서 함수 참조를 제공하는 방법을 고려할 수 있다. 이렇게 하면 값이 널이 아닐 때 호출을 실행하지 않음으로써 성능상의 이득을 얻을 수 있다.
 

Record 클래스

자바 앱 빌드에서 흔히 필요한 부분은 불변성 DTO(데이터 전송 객체)다. DTO는 데이터베이스, 파일 시스템 및 기타 데이터 저장소에서 데이터를 모델링하는 데 사용된다. 전통적으로 DTO는 getter가 액세스하는 일 없이 멤버가 생성자를 통해 설정되는 클래스를 만드는 방법으로 생성된다. 자바 14에서 처음 도입되어 자바 15에서 개선된 새로운 record 키워드가 바로 이 목적을 위한 간편한 방법을 제공한다.
 
예시 3은 record 형식이 도입되기 전, 기존의 DTO 정의와 사용 방법을 보여준다.

예시 3. 간단한 불변성 DTO

public class MyClass {
    public static void main(String args[]) {
      Pet myPet = new Pet("Sheba", 10);

      System.out.println(String.format("My pet %s is aged %s", myPet.getName(), myPet.getAge()));
    }
}
class Pet {
    String name;
    Integer age;
    public Pet(String name, Integer age){
        this.name = name;
        this.age = age;
    }
    public String getName(){
        return this.name;
    }
    public Integer getAge(){
        return this.age;
    }
}

예시 4와 같이 record 키워드를 사용해서 거추장스러운 요소를 대부분 없앨 수 있다.

예시 4. record 키워드 사용 

public class MyClass {
    public static void main(String args[]) {
      Pet myPet = new Pet("Sheba", 10);

      System.out.println(String.format("My pet %s is aged %s", myPet.getName(), myPet.getAge()));
    }
}

public record Pet(String name, Integer age) {}

데이터 객체를 사용하는 클라이언트 코드가 변경되지 않은 것을 볼 수 있다. 일반적으로 정의되는 객체와 똑같이 작동한다. record 키워드는 매우 똑똑해서, 간단한 정의를 통해 어떤 필드가 존재하는지를 추론한다.
 
또한 record 형식은 equals(), hashCode(),toString()의 기본 구현을 정의하며, 개발자가 이러한 기본 구현을 재정의하도록 허용한다. 맞춤형 생성자를 제공할 수도 있다.
 
참고로 record는 서브클래스가 불가능하다.
 

새로운 String 메서드

자바 10과 자바 12에서 유용한 String 메서드가 여러 개 추가됐다. 문자열 조작 메서드 외에 텍스트 파일 액세스를 간소화하기 위한 2개의 새로운 메서드가 도입됐다.
 
자바 10의 새로운 String 메서드 :

•    isBlank() : 문자열이 비어 있거나 문자열에 공백만 포함된 경우(탭 포함) true를 반환한다. 길이가 0인 경우에만 true를 반환하는 isEmpty()와는 다르다.

•    lines() : 문자열을 각각 라인 하나를 포함한 여러 문자열 스트림으로 분할한다. 라인은 /r 또는 /n 또는 /r/n으로 정의된다. 아래 예시 5를 참고하라.

•    strip(), stripLeading(), stripTrailing() : 각각 처음과 끝, 처음, 그리고 끝의 공백을 제거한다.
 
•    repeat(int times) : 원래의 문자열을 받아서 지정된 횟수만큼 반복하는 문자열을 반환한다.

•    readString() : 파일 경로에서 문자열로 직접 읽어들일 수 있도록 한다(예시 6 참조).

•    writeString(Path path) : 지정된 경로의 파일에 직접 문자열을 쓴다.

자바 12의 새로운 String 메서드 :
•    indent(int level): 지정한 만큼 문자열을 들여쓰기한다. 음수 값은 선행 공백에만 영향을 미친다.

•    transform(Function f): 지정된 람다를 문자열에 적용한다.


예시 5. String.lines() 예

import java.io.IOException;
import java.util.stream.Stream;
public class MyClass {
    public static void main(String args[]) throws IOException{
      String str = "test \ntest2 \n\rtest3 \r";
      Stream lines = str.lines();
      lines.forEach(System.out::println);
    }
}

/*
outputs:
test
test2
test3
*/


예시 6. String.readString(Path path) 예

Path path = Path.of("myFile.txt"); 
String text = Files.readString(path);
System.out.println(text);

 

switch 식

자바 12에는 switch를 문 내에서 인라인으로 사용할 수 있게 해주는 switch 식이 도입됐다. 즉, switch 식은 값을 반환한다. 또한 자바 12는 명시적인 break의 필요성을 없애는 화살표 구문도 제공한다. 자바 13은 한 걸음 더 나아가 switch 케이스가 반환하는 값을 명시적으로 나타내는 yield 키워드를 도입했다. 자바 14에서는 새로운 switch 식이 완전한 기능으로 도입됐다.
 
몇 가지 예를 보자. 먼저 예시 7에는 전통적인(자바 8) 형식으로 된 switch 문의 (상당히 부자연스러운) 예가 나와 있다. 이 코드는 변수(message)를 사용해서 숫자의 이름(알려진 경우)을 출력한다.

예시 7. 과거의 자바 switch

class Main { 
  public static void main(String args[]) {
    int size = 3;
    String message = "";

switch (size){
 case 1 :
message = "one";
 case 3 :
   message = "three";
break;
 default :
message = "unknown";
break;
}

System.out.println("The number is " + message);
  }
}

이 코드는 상당히 장황하고 까다롭다. 사실 이미 오류가 있다! 잘 보면 break가 누락되었음을 알 수 있다. 예시 8은 switch 식을 사용해 코드를 간소화한 모습이다.

예시 8. 새로운 switch 식

class NewSwitch { 
  public static void main(String args[]) {
    int size = 3;

    System.out.println("The number is " +
      switch (size) {
        case 1 -> "one";
        case 3 -> "three";
        default -> "unknown";
      }
    );
  }
}

예시 8에서 switch 식은 System.out.println 호출 안에 들어가 있다. 이것만으로 가독성 측면에서 큰 진전이며 불필요한 message 변수도 없어진다. 또한 화살표 구문은 break 문을 제거해 코드의 양을 줄여준다. (yield 키워드는 화살표 구문을 사용하지 않을 때 사용됨)
 
새로운 switch 식 구문에 대한 더 자세한 내용은 여기서 볼 수 있다.
 

텍스트 블록

자바 13은 텍스트 블록을 통해 자바에서 복잡한 텍스트 문자열을 다룰 때의 오랜 불편함을 해소했다. 자바 14는 텍스트 블록 지원을 더 개선했다.
 
JSON, XML, SQL 등의 여러 중첩된 이스케이프 계층을 다루다 보면 정신을 차리기가 어렵다. 사양에는 다음과 같이 설명돼 있다.
 
자바에서 HTML, XML, SQL 또는 JSON 스니펫을 문자열 리터럴 안에 내장하는 경우 이 스니펫이 포함된 코드가 컴파일되려면 일반적으로 먼저 이스케이프 및 연결과 관련해 상당한 편집이 필요하다. 스니펫은 많은 경우 읽기가 어렵고 유지보수도 까다롭다.

예시 9에서 새로운 텍스트 블록 구문을 사용해 JSON 스니펫을 만드는 것을 볼 수 있다.

예시 9. 텍스트 블록을 사용한 JSON

class TextBlock { 
  public static void main(String args[]) {
    String json = """
      {
        "animal" : "Quokka",
        "link" : "https://en.wikipedia.org/wiki/Quokka"
      }
    """;

    System.out.println(json);
  }
}

예시 9에는 이스케이프 문자가 보이지 않는다. 3중 따옴표 구문을 유의해서 보자.
 

Sealed 클래스

자바 15(JEP 260)에는 sealed 클래스 개념이 도입됐다. 새로운 sealed 키워드는 인터페이스 서브클래스가 가능한 클래스를 정의할 수 있게 해준다. 한 가지 예를 보는 것이 천 마디 설명보다 낫다. 예시 10을 보자.

예시 10. sealed 클래스 예

public abstract sealed class Pet
    permits Cat, Dog, Quokka {...}

여기서 인터페이스 디자이너는 sealed 키워드를 사용해서 Pet 클래스를 확장하도록 허용된 클래스를 지정한다.


참고 : https://www.itworld.co.kr/t/61023/%EA%B0%9C%EB%B0%9C%EC%9E%90/208787

 

끝!

댓글
최근에 올라온 글
최근에 달린 댓글
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31