[JAVA] Java Version 8 vs 17
처음 자바를 접했을 때 영문도 모른채 조교의 안내대로 JAVA 버전 8을 설치하여 사용하다보니 자연스럽게 사용해왔던 8버전, 그리고 현재 스프링 부트 3.0을 사용하기 위해 버전 업그레이드를 따라가면서 사용하게 된 17버전에 대한 차이를 알아보며 내가 자연스럽게 사용하고 있는 기능에 대한 복습과 놓치고 있던 점에 대해 학습하고자 한다.
개요
JAVA 8
- Lambda
- Stream
- interface default Method
- 인터페이스가 추상메소드말고 default 선언으로 메소드를 미리 선언할 수 있는 기능 ⇒ 추후에 overriding 가능
- Optional
- LocalDateTime
JAVA 17
- Pattern Matching for Switch(17에서 등장)
- Sealed Classes (15에서 등장, 17에서 정식 지원)
- Foreign Function & Memory API (JNI 대체, 17에서 등장 incubator = preview 이전 단계)
JAVA 8
Lambda
함수를 하나의 표현식으로 나타낸 것
// 1. 반복문 - Iterator
for(Integer num: numList) {
System.out.println(num);
}
// 2. 람다 표현식
numList.forEach(x -> System.out.println(x));
장점 : 간결하다
단점 : 재활용 불가능, 복잡해질수록 디버깅 어려움
Stream
람다 활용 기술 중 하나
Collection의 요소들을 foreach 등으로 루프를 돌며 하나씩 처리하던 것에 비해 람다 함수들을 각각 병렬 처리로 순차적으로 적용할 수 있음.
ArrayList<String> list = new ArrayList<String>(Arrays.asList("a", "b", "c"));
// 반복문
for (String value : list) {
if (StringUtils.equals(value, "b") {
System.out.println("값 : " + value);
}
}
// Stream
list.stream()
.filter("b"::equals)
.forEach(System.out::println);
장점: 병렬처리 가능하기에 빠르다
단점: Stream 재사용 불가(동일한 스트림 재사용시 에러), Stream 병렬처리로 발생하는 데드락에 대한 위험성 존재
Interface Default Method
인터페이스가 추상메소드말고 default, static 선언으로 메소드를 미리 선언할 수 있는 기능 ⇒ 추후에 overriding 가능
- default 메서드참조 변수로 호출
- 재정의 o
- static 메서드클래스 메서드이기 때문에 객체 생성하지 않고 직접 사용
- 재정의 x
Optional
Optional은 null이 될 수 있는 값을 감싸는 Wrapper Class
참조하더라도 NPE(NullPointerException)이 발생하지 않도록 함
장점 : NPE 처리, 값의 존재 유무에 따라 동작 다르게 처리하는 경우에 유용
단점 : Wrapper Class로 감쌌다가 푸는 과정에 오버헤드 발생
LocalDateTime
불변 시간 정보 가짐
JAVA 17
Pattern Matching for Switch
Day day = ...
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> {
System.out.println("Case에 대한 처리가 길어지고 코드 블럭이 필요하다면...");
System.out.println("Yield를 통해 값을 반환한다");
yield 7;
}
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new RuntimeException("잘못된 입력"); // 값을 리턴할 경우 default 문장이 반드시 있어야 한다.
};
System.out.println("numLetters = " + numLetters);
Day day = Day.WRONGINPUT;
// 실행결과: **Exception in thread "main" java.lang.RuntimeException: 잘못된 입력**
Day day = Day.TUESDAY;
// 실행결과: Case에 대한 처리가 길어지고 코드 블럭이 필요하다면...
// Yield를 통해 값을 반환한다
// numLetters = 7
- Switch 문 값 직접 반환
- yield 예약어 이용한 값 리턴 방식 추가
- Case 문 람다식 지원
Sealed Class
무분별한 상속 막기 ⇒ 지정한 클래스 외 상속을 허용하지 않음
public sealed interface PhoneBrand permits Galaxy, IPhone{}
// 정상 동작
public final class Galaxy implements PhoneBrand {}
public non-sealed class IPhone implements PhoneBrand {}
// 에러: 허용되지 않은 클래스 구현,상속 불가
public class Hyundai implements PhoneBrand {}
// 에러: final class는 어떤 클래스도 상속할 수 없음
public class S23 extends Galaxy {}
// 정상: non-sealed class는 어떤 클래스도 상속 가능
public class S23 extends IPhone {}
제약 조건
- 상속/구현 클래스는 final, non-sealed, sealed 중 하나로 선언되어야 함
- final class은 어떤 클래스도 상속할 수 없음
- non-sealed class는 어떤 클래스도 상속할 수 있음
- Permitted Subclass들은 동일한 모듈에 속해야 함, 이름이 지정되지 않은 모듈에 선언시 동일한 패키지에 속해야함
- Permitted Subclass는 Sealed Class를 직접 확장해야 함
⇒ Super Class의 Sub Class들을 명확히 인지하자
Ref)
Java version history - Wikipedia
[PMJ] Practical 모던 자바 - 스위치 표현식 (switch expressions) (tistory.com)
Optional 제대로 알기, 면접 대비! (+간단 실무 코드 예시) (tistory.com)