-
자바 17로 바꿔야 할까? (자바 JDK 10 ~ 17 정리)JAVA/자바공부 2022. 10. 1. 00:16
잠이 안 와서 유튜브에 보는데
intellij conf에 자바 17에 대한 발표가 있었다.정리해 본다.
출처
Project Repo : github
Intelij Conf 2022 : youtube
🧑🏫 발표자가 생각하는 Java 17 요약
- 17 오면서 성능 향상 (빠르다, 메모리 조금 쓴다), 새로운 기능 추가 됨
- 자바 8 쓰는 중이라면 11 건너뛰고 바로 17로 가자 (라이브러리 버전들이 영향받을 것…그렇지만)
- JDK 17은 발표된 지 1년 지났고 라이브러리들 안정화된 것 같음 (17은 Sept 2021 발표)
- JDK 19도 이미 출시
- JDK 21(LTS) 출시 예정 (Sept 2023, LTS 출시가 2년 주기로 바뀜 관련 기사)
- JDK 17은 6년 이상 지원 될 것
1. 발표자
- Nikhil Nanivadekar
- Principle Engineer with Amazon
- 시애틀 거주
- 자바 챔피언 (전 세계 30명 정도 있다고 함)
- 트위터 : NikhilNanivade
Nikhil Nanivadekar (@NikhilNanivade) / 트위터
Project lead Eclipse Collections (https://t.co/Bz4h5Ytpb8) Software Developer, Mechanical Engineer, Java Champion. All opinions stated by me are my own.
twitter.com
2. 주제 : 자바 17로 바꿔야 할까?
자바 17에서 변한 것
2.1. 더 좋아진 성능
- Java 8 vs 11 vs 17 성능 측정 결과는 JMH Tests을 사용해서 테스트함 (Java Microbenchmark Harness)
- Interger의 속도가 매우 빨라짐 Map.put, Map.get
- String의 경우 size가 커지면 성능이 좋아짐 (50,000 건부터 점점 더 빠름)
- 17은 메모리를 덜 쓴다.
🧑🏫 성능 측정 결과 보는 곳 : 깃허브
깃 타고들어가면 이런것 볼 수 있다. 2.2. 새로 추가된 기능 (JDK 10 ~ JDK 17)
var (JDK 10)
- Local variable type inference
- 컴파일러가 type 알아서 확인해줌
- null로 초기화할 수 없다.
- 람다 표현식 할당 할 수 없다.
- 다형성 코드에서 사용 피해라.
@Test public void var() { Map<Integer, String> map = Map.of(1, "One", 2, "Two"); var withVar = Map.of(1, "One", 2, "Two"); // Map으로 알아서 type check Assertions.assertEquals(map, withVar); }
Switch Stataments (JDK 14)
- 기존의 스위치문 (가독성…)
private String getQuarterOldSwitch(Integer monthNumber) { switch (monthNumber) { case 1: return "Q1"; case 2: return "Q1"; case 3: return "Q1"; case 4: return "Q2"; case 5: return "Q2"; case 6: return "Q2"; case 7: return "Q3"; case 8: return "Q3"; case 9: return "Q3"; case 10: return "Q4"; case 11: return "Q4"; case 12: return "Q4"; default: return "Not a month in year"; } }
- 업그레이드된 스위치문
private String getQuarterNewSwitch(Integer monthNumber) { return switch (monthNumber) { case 1, 2, 3 -> "Q1"; case 4, 5, 6 -> "Q2"; case 7, 8, 9 -> "Q3"; case 10, 11, 12 -> "Q4"; default -> "Not a month in year"; }; } private String getQuarterNewSwitch(Integer monthNumber) { final String quarter = switch (monthNumber) { case 1, 2, 3 -> "Q1"; case 4, 5, 6 -> "Q2"; case 7, 8, 9 -> "Q3"; case 10, 11, 12 -> "Q4"; default -> "Not a month in year"; }; return quarter; }
- 표현식에 yeild value 사용할 수 있다.
private String getQuarterYieldSyntax(Integer monthNumber) { return switch (monthNumber) { case 1, 2, 3 -> "Q1"; case 4, 5, 6 -> "Q2"; case 7, 8, 9 -> "Q3"; case 10, 11, 12 -> { System.out.println("Yay Last Quarter"); yield "Q4"; } default -> "Not a month in year"; }; }
- Switch with Enums
- 컴파일 safety 증가..?
public enum Months { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC } private String getQuarterEnum(Months month) { return switch (month) { case JAN, FEB, MAR -> "Q1"; case APR, MAY, JUN -> "Q2"; case JUL, AUG, SEP -> "Q3"; case OCT, NOV, DEC -> "Q4"; // No need for default as all possible values are covered (exhaustive). }; }
Text Blocks (JDK 15)
- 기존의 String 사용법
String json = "{\\n" + " \\"firstName\\": \\"Nikhil\\",\\n" + " \\"lastName\\": \\"N\\",\\n" + " \\"city\\": \\"Seattle\\",\\n" + " \\"phone\\": 123\\n" + "}";
- text block 등장 (따옴표가 3개!)
String textBlockJson = """ { "firstName": "Nikhil", "lastName": "N", "city": "Seattle", "phone": 123 }""";
- formatted syntax를 사용해서 string 다루기
String textBlockJson = """ { "firstName": "%s", "lastName": "%s", "city": "%s", "phone": %d }"""; String formattedTextBlockJson = textBlockJson.formatted( "Nikhil", "N", "Seattle", 123);
Helpful Null Pointer Exceptions (JDK 14)
- null 발생했을 때 메시지, 플래그를 던져줌 (NPE)
자바 13 이전
Person person = new Person("Nikhil", "N", null); String lowercaseCity = persoon.getAddress().getCity().toLowerCase(); /** 자바 13 이전의 nullException 메시지 Exception in thread "main" java.lang.NullPointerException at nikhil.nani.code.examples.ExamplesHelpfulNPEsTest.helpfulNpesTest1(ExamplesHelpfulNPEsTest.java:13) **/
자바 14 이후
- 실제 null 이 일어난 이유를 상세하게 설명해 준다.
- 디버깅을 매우 쉽게 해 줌 → 어떤 값이 null 인지 알려준다.
Person person = new Person("Nikhil", "N", null); String lowercaseCity = persoon.getAddress().getCity().toLowerCase(); /** 자바 14 이후 nullException 메시지 java.lang.NullpointerException : Cannot invoke "nikhil.nani.code.examples.ExamplesHelpfulNPEsTest$Address.city()" because the return value at "nikhil.nani.code.examples.ExamplesHelpfulNPEsTest$Address()" is null at nikhil.nani.code.examples.ExamplesHelpfulNPEsTest.helpfulNpesTest1(ExamplesHelpfulNPEsTest.java.13) **/
Person person = new Person("Nikhil", "N", new Address("", "", null)); String lowercaseCity = person.address().city().toLowerCase(); /** Prints: java.lang.NullPointerException: Cannot invoke "String.toLowerCase()" because the return value of "nikhil.nani.code.examples.ExamplesHelpfulNPEsTest$Address.city()" is null at nikhil.nani.code.examples.ExamplesHelpfulNPEsTest.helpfulNpesTest2(ExamplesHelpfulNPEsTest.java:23) **/
Pattern Matching for instanceof (JDK 16)
- 객체의 컴포넌트를 적출하기 더 간결하고 safety
- 기존의 instanceof 사용법 → 주로 casting 할 때 아래처럼 사용
private String withoutPatternMatching(Object input) { if (input instanceof String) { String string = (String) input; return "This is a String:" + string; } if (input instanceof Integer) { Integer integer = (Integer) input; return "This is an Integer:" + integer; } if (input instanceof Double) { Double dbl = (Double) input; return "This is a Double:" + dbl; } return ""; }
- Pattern Matching for Instanceof
- input객체가 aString이고 aString은 String이라는 것을 확인
// Note each pattern variable's scope is only within the respective flow private String withPatternMatching(Object input) { if (input instanceof String aString) { // Scope of aString is only within this block return "This is a String:" + aString; } if (input instanceof Integer anInteger) { // Scope of anInteger is only within this block return "This is an Integer:" + anInteger; } if (input instanceof Double aDouble) { // Scope of aDouble is only within this block return "This is a Double:" + aDouble; } return ""; }
Records (JDK 16)
- Data를 A to B로 옮기려는 홀더라면?
- https://www.infoq.com/articles/data-oriented-programming-java/
- 모든 필드는 private final이다.
- instance filelds는 선언할 수 없다. (immutable)
- accessors, hashcode, toString, equals 자동생성
- default implementations override 가능
- 커스텀 메서드 데피니션 작성 가능
- 읽기 전용 불편 DTO라 생각하면 되겠다. Kotlin의 Data class
옛날 스타일
public final class PersonNonRecord { private final String firstName; private final String lastName; /** * Constructor, Accessor, hashcode, equals, toString */ }
Records 적용
public record PersonRecord(String firstName, String lastName) { public String getFullName() { return firstName + ' ' + lastName; } @Override public String toString() { return "Person{" + "firstName='" + firstName + '\\'' + ", lastName='" + lastName + '\\'' + '}'; } }
Sealed Classes (JDK 17)
- 원하는 클래스만 상속할 수 있도록 조작할 수 있는 기능
- sealed 명령어로 class 만들면 밀봉
- permit 뒤에 오는 sub class만 상속을 받도록 제어할 수 있다.
- non-sealed
- non-final class는 sub-classes를 any number 상속할 수 있다.
- sealed 명령어로 class 만들면 밀봉
- 예시와 코드를 통한 설명
- User (Sealed Interface)
public sealed interface User permits Owner, Admin, Resident { default String login() { return "Logged in"; } }
- Owner : Final Class
public final class Owner implements User { }
- Admin : Sealed Class (permits 된 것만 상속 가능)
public sealed class Admin implements User permits SuperAdmin { }
- Resident : Non-Sealed Class
public non-sealed class Resident implements User { }
하위 클래스
- SuperAdmin, TempAdmin
public final class SuperAdmin extends Admin { } // This test passes Assertions.assertEquals("Logged in", superAdmin.login()); // Below class TempAdmin does not compile as TempAdmin is not permitted in the sealed hierarchy public final class TempAdmin extends Admin { }
- DayGuest, Overnight Guest
// Since Resident is non-sealed, it is open for any number of sub-classes, hence it opens up the hierarchy public final class DayGuest extends Resident { } public final class OvernightGuest extends Resident { } // These tests passed Assertions.assertEquals("Logged in", dayGuest.login()); Assertions.assertEquals("Logged in", overnightGuest.login());
지워진 기능
- Nashorn Engine (JDK 15)
- CMS Garbage Collector (JDK 14)
- Strongly Encapsulate JDK Internals (JDK 17)
- And a lot more deprecations…
Garbage Collector
- Serial GC
- Parallel GC
- G1 GC
- ZGC
- Shenandoah GC
- Epsilon (Experimental as of Sept 2022)
반응형'JAVA > 자바공부' 카테고리의 다른 글
자바 (0) 2023.02.20 정규식 표현 (자바, 코틀린) - 전화번호, 우편번호, 이메일 (0) 2022.10.14 Optional<> 과 Null (이론편) (0) 2022.07.15 TIL - Final 키워드 (3) 2022.02.11 TIL - 제네릭(generic) 정리 (0) 2022.02.04