자바(SE)

[JDK] 버전별 특징 - JDK11

은서파 2023. 5. 22. 15:06

JDK11은 JDK1.8 이후 등장한 첫 LTS(Long Term Support)버전이다. 

프로그래밍적인 요소는 아니지만 11로 오면서 가장 큰 변화는 Oracle JDK를 상업용으로 사용할 때에는 라이센스가 필요하며 대신 OpenJDK(https://openjdk.org/projects/jdk/), Zulu(https://www.azul.com/downloads/#zulu) 등을 사용해야 한다.

기능상 차이점은 없기 때문에 그냥 무료의 JDK들을 설치해서 사용하면 된다.

개발적인 측면의 신 기능들

 

String 클래스에 새로운 메서드들 추가

  • isBlank:  문자열이 의미있는 내용으로 채워져있는지 검사하기 위해서 기존에는 isEmpty를 사용할 수 있었는데 이 녀석은 그냥 문자열의 길이가 0인지만 보는 녀석이었다. 반면 isBlank는 white space를 제외하고 판단한다.
@Test
public void stringMethodTest(){
    String hello = " ";
    Assertions.assertFalse(hello.isEmpty());
    Assertions.assertTrue(hello.isBlank());
}
  • lines: 여러 줄로 입력된 문자열을 구분자로 분리한 Stream을 반환하는 메서드이다. 이때 구분자는 \r, \n, \r\n 이 사용될 수 있다.
  • strip, stripLeading, stripTrailing: 기존의 trim 메서드가 세분화 되었다. trim은 시작과 끝에서의 공백을 모두 제거했다면 이 기능은 strip이 물려 받고 앞에서(stripLeading), 뒤에서(stripTrailing) 공백을 제거할 수 있게 되었다.
@Test
public void linesStripTest(){
    String multiStr = "Hello  \r\n  Happy  \r \n  Java\nWorld";
    multiStr.lines().filter(line -> !line.isBlank())
                    .forEach(line -> System.out.println(line+" : "+line.length()));

    List<String> list =multiStr.lines().filter(line -> !line.isBlank())
                                       .map(String::strip)
                                       .collect(Collectors.toUnmodifiableList());

    Assertions.assertEquals(list, List.of("Hello", "Happy", "Java", "World"));
}
  • repeat: 문자열을 주어진 count만큼 반복해서 새로운 문자열을 만들어준다.
@Test
public void repeatTest(){
    String sample = "Hi";
    String repeated = sample.repeat(4);
    Assertions.assertEquals(repeated, sample+sample+sample+sample);
}

 

Files를 이용한 문자열 직접 파일에 쓰기 및 읽기

기존에는 문자열을 파일에 저장하거나 파일에서 읽어오기 위해서 Stream을 연결해야했지만 Files에서 제공하는 readString, writeString을 이용하면 Stream없이 쉽게 처리할 수 있게 되었다.

@Test
public void filesTest() throws IOException {
    String content = "Sample text";
    Path target = Path.of("c:/Temp/test.txt");
    // 파일에 쓰기
    Path filePath = Files.writeString(target, content);
    // 파일에서 읽어오기
    String fileContent = Files.readString(filePath);
    assertEquals(fileContent, content);
}

 

Collection 내용을 배열로 만들기

Collection을 이용해서 배열을 생성할 때 toArray 함수를 사용하는데 이때 lambda 식을 이용할 수 있게 되었다.

@Test
void test() {
    List<String> list = Arrays.asList("1","2","3");
    // String [] arr = list.toArray(new String[list.size()]); // 기존
    String [] arr = list.toArray(String[]::new); // JDK 11
}

 

Predicate에 static boolean not 메서드 추가

Predicate에 static한 not 메서드가 추가되었다. 특히 Stream을 구성하는 요소가 자체로 boolean을 반환할 때 유용할 듯 하다.

@Test
public void testPredicate(){
    String [] data = {"Hello", "", "\n", "Java", "World"};
    long cnt = Arrays.stream(data).filter(Predicate.not(String::isBlank )).count();
    assertEquals(cnt, 3);
}

 

lambda 식에서 local-variable 문법

이제 lambda 식에 사용된 변수의 타입 var 변수에 타입 annotation을 선언할 수 있게 되었다.

@Test
public void localVarTest() {
    String[] strs = {"Hello", "Java", "World"};
    String resultString = Arrays.stream(strs)
                                .map(x -> x.toUpperCase())        // x에 대한 한정 불가
                                .collect(Collectors.joining(", "));
    assertEquals(resultString, "HELLO, JAVA, WORLD");

    resultString = Arrays.stream(strs)
                          .map((@Deprecated var x) -> x.toUpperCase())
                          .collect(Collectors.joining(", "));
    assertEquals(resultString, "HELLO, JAVA, WORLD");
}

JDK 10에 추가된 var 키워드를 보고 뭐에 쓰는 녀석일까 궁금했는데 상당히 유의미한 용법이 생긴듯 하다. lambda 식을 사용할 때 타입이 유동적인 경우 파라미터의 타입을 생략할 수 있는데 이 경우는 그 타입에 대한 annotation 추가가 불가하다.

이제 var 키워드를 이용할 수 있기 때문에 이 변수에 타입 annotation 사용이 가능해졌다. 사실 @Deprecated를 쓸일은 없겠지만 @Nullable 등은 유용할 듯 싶다.