# 자바 버전별 차이
# Java 8
# Lambda
- 람다 표현식(lambda expression)이란 간단히 말해 메소드를 하나의 식으로 표현한 것입니다.
- 식별자 없이 실행할 수 있는 함수 표현식을 의미하며, 따라서 익명 함수(anonymous function)라고도 부릅니다.
- 메소드를 람다 표현식으로 표현하면 클래스를 만들고 객체를 생성하지 않아도 메소드를 사용할 수 있습니다.
- 람다 표현식은 메소드의 매개변수로 전달될 수도 있고, 메소드의 결괏값으로 반환될 수도 있습니다.
- 람다 표현식은 기존의 불필요한 코드를 줄여주고, 작성된 코드의 가독성을 높이는 데 그 목적이 있습니다.
Runnable runnable = new Runnable(){
@Override
public void run(){
System.out.println(*"Hello world !"*);
}
};
Runnable runnable = () -> System.out.println("Hello world!");
# Stream
- 자바에서는 많은 양의 데이터를 저장하기 위해서 배열이나 컬렉션을 사용합니다.
- 이때, 저장된 데이터에 접근하기 위해서는 반복문이나 반복자(iterator)를 사용하여 매번 코드를 작성해야 합니다.
- 그러나 해당 코드는 길이가 너무 길고 가독성도 떨어지며, 코드의 재사용이 거의 불가능합니다.
- 이 문제점을 극복하기 위해서 Java SE 8 버전부터 도입된 방법이 바로 스트림(stream) API입니다.
- 스트림 API는 데이터를 추상화하여 다루므로, 다양한 방식으로 저장된 데이터를 읽고 쓰기 위한 공통된 방법을 제공합니다.
- 따라서 스트림 API를 이용하면 배열이나 컬렉션뿐만 아니라 파일에 저장된 데이터도 모두 같은 방법으로 다룰 수 있습니다.
List<String> list = Arrays.asList("aa", "bb", "cc", "dd", "ee");
list.stream()
.filter(name -> name.startsWith("a"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
# interface default method
- interface 클래스에 구현 메서드를 작성할 수 있게 되었습니다.
- 인터페이스 클래스 내부에 dafault와 static 키워드를 사용하면 구현 메서드를 작성 할 수 있습니다.
# default메소드
- 인터페이스가 default키워드로 선언되면 메소드가 구현될 수 있다. 또한 이를 구현하는 클래스는 default메소드를 오버라이딩 할 수 있다.
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){
return i + j;
}
}
- 인터페이스가 변경이 되면, 인터페이스를 구현하는 모든 클래스들이 해당 메소드를 구현해야 하는 문제가 있습니다.
- 이런 문제를 해결하기 위하여 인터페이스에 메소드를 구현해 놓을 수 있도록 했습니다.
# static메소드
public interface Calculator {
public int plus(int i, int j);
public int multiple(int i, int j);
default int exec(int i, int j){
return i + j;
}
public static int exec2(int i, int j){ //static 메소드
return i * j;
}
}
- 인터페이스에 static 메소드를 선언함으로써, 인터페이스를 이용하여 간단한 기능을 가지는 유틸리티성 인터페이스를 만들 수 있게 되었습니다.
# Optional
- 자바에서는
null
을 다루는 것이 까다롭고,NPE
가 많이 발생합니다. - 그래서 대부분의 코드에
null
체크 로직이 포함됩니다. - 자바 8 버전 이후부터는
null
체크를 깔끔하게 하는Optional
클래스를 사용할 수 있게 되었습니다.
# java.time
- JDK 1.0에서는 Date 클래스를 사용하여 날짜에 관한 처리를 수행했습니다.
- 하지만 Date 클래스는 현재 대부분의 메소드가 사용을 권장하지 않고(deprecated) 있습니다.
- JDK 1.1부터 새롭게 제공된 Calendar 클래스는 날짜와 시간에 대한 정보를 얻을 수는 있지만, 다음과 같은 문제점을 가지고 있습니다.
- Calendar 인스턴스는 불변 객체(immutable object)가 아니라서 값이 수정될 수 있습니다.
- 윤초(leap second)와 같은 특별한 상황을 고려하지 않습니다.
- Calendar 클래스에서는 월(month)을 나타낼 때 1월부터 12월을 0부터 11까지로 표현해야 하는 불편함이 있습니다.
- 따라서 많은 자바 개발자들은 Calendar 클래스뿐만 아니라 더 나은 성능의 Joda-Time이라는 라이브러리를 함께 사용해 왔습니다.
- Java SE 8 버전에서는 이러한 Joda-Time 라이브러리를 발전시킨 새로운 날짜와 시간 API인 java.time 패키지를 제공합니다.
- java.time 패키지는 위와 같은 문제점을 모두 해결했으며, 다양한 기능을 지원하는 다수의 하위 패키지를 포함하고 있습니다.
LocalDate today = LocalDate.now();
System.out.println("올해는 " + today.getYear() + "년입니다.");
LocalDate otherDay = today.withYear(1982);
System.out.println("올해는 " + otherDay.getYear() + "년입니다.");
# Java 9
# 컬렉션
- 컬렉션에 배열을 쉽게 생성할 수 있느 메서드가 추가되었습니다.
List<String> list = List.of("one", "two", "three");
Set<String> set = Set.of("one", "two", "three");
Map<String, String> map = Map.of("foo", "one", "bar", "two");
# Java 10
- var 키워드
- 병렬 처리 가비지 컬렉션 도입으로 인한 성능 향상
- JVM 힙 영역을 시스템 메모리가 아닌 다른 종류의 메모리에도 할당 가능
# 지역 변수 유형 추론: var-keyword
// Pre-Java 10
String myName = "Marco";
// With Java 10
var myName = "Marco"
- JAVA에서 var 예약어를 사용하면 중복을 줄임으로써 코드를 간결하게 만들 수 있습니다.
- var 키워드는 지역 변수 타입 추론을 허용합니다.
- 메서드 내부의 변수에만 적용 가능합니다.
# Java 11
- Oracle JDK와 OpenJDK 통합
- Oracle JDK가 구독형 유료 모델로 전환
- 서드파티 JDK 로의 이전 필요
- lambda 지역변수 사용법 변경
- 기타 추가
# Run Source Files
- Java 소스 파일 을 먼저 컴파일 하지 않고도 실행할 수 있습니다.
- java 명령을 사용하여 파일을 직접 실행할 수 있습니다.
$ java HelloWorld.java
Hello World
# 람다 매개변수에 대한 지역 변수 유형 추론(var)
- 람다 표현식에서 타입 추론(var)을 사용할 수 있게 되었습니다.
// before java 11
Consumer<String> test = s -> System.out.println(s);
// after java 11
Consumer<String> test = (var s) -> System.out.println(s);
# String, Files 클래스
- Strings and Files에는 몇 가지 새로운 메서드 추가
"Marco".isBlank();
"Mar\nco".lines();
"Marco ".strip();
Path path = Files.writeString(Files.createTempFile("helloworld", ".txt"), "Hi, my name is!");
String s = Files.readString(path);
# Java 12
- 유니코드 11 지원과 새로운 스위치 표현식의 preview
# Java 13
- 기본적으로 유니코드 12.1 지원과 두 가지 새롭거나 개선된 preview 기능(향후 변경될 수 있음)이 제공
# 스위치 표현식(preview)
- 이제 스위치 표현식이 값을 반환 가능하며 fall-through/break 문제 없이 표현식에 람다 스타일 구문을 사용 가능합니다.
스위치 표현식 전
switch(status) {
case SUBSCRIBER:
// code block
break;
case FREE_TRIAL:
// code block
break;
default:
// code block
}
스위치 표현식 후
boolean result = switch (status) {
case SUBSCRIBER -> true;
case FREE_TRIAL -> false;
default -> throw new IllegalArgumentException("hello world");
};
# Multiline Strings (Preview)
스위치 표현식 전
String htmlBeforeJava13 = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
스위치 표현식 후
String htmlWithJava13 = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
# Java 14
- 스위치 표현식 표준화
- instanceof 패턴 매칭 (preview)
- record (data object) 선언 기능 추가 (preview)
# 스위치 표현(Standard)
- 버전 12 및 13에서 preview 였던 스위치 표현식이 이제 표준화 되었습니다.
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
default -> {
String s = day.toString();
int result = s.length();
yield result;
}
};
# record(preview)
- Java로 많은 상용구를 작성하는 고통을 완화하는 데 도움이 되는 레코드 클래스가 있습니다.
- 데이터, (잠재적으로) getter/setters, equals/hashcode, toString만 포함
레코드 사용 전
final class Point {
public final int x;
public final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
}
// state-based implementations of equals, hashCode, toString
// nothing else
레코드 사용 후
record Point(int x, int y) { }
# NullPointerExceptions
- 마지막으로 NullPointerExceptions는 정확히 어떤 변수가 null 인지 설명해줍니다.
author.age = 35;
---
Exception in thread "main" java.lang.NullPointerException:
Cannot assign field "age" because "author" is null
# Pattern Matching For InstanceOf (Preview)
자바 14 전
if (obj instanceof String) {
String s = (String) obj;
// use s
}
- 이전에는 다음과 같이 instanceof 내부에서 객체를 캐스팅이 필요합니다.
자바 14 후
if (obj instanceof String s) {
System.out.println(s.contains("a"));
}
- 이제 이 작업을 수행하여 캐스트를 효과적으로 삭제 가능합니다.
# Java 15
- Text-Blocks / Multiline Strings
- Records & Pattern Matching(2차 preview, 상단 Java 14 참조)
- 스케일링 가능한 낮은 지연의 가비지 컬렉터 추가(ZGC)
- 레코드 (2차 preview, 상단 Java 14 참조)
- Sealed Classes - Preview
- Nashorn JavaScript Engine 제거
# Text-Blocks / Multiline Strings
# Sealed Classes - Preview
- 상속 가능한 클래스를 지정할 수 있는 봉인 클래스가 제공됩니다.
- 상속 가능한 대상은 상위 클래스 또는 인터페이스 패키지 내에 속해 있어야 합니다.
public abstract sealed class Shape
permits Circle, Rectangle, Square {...}
즉, 클래스가 public인 동안 하위 클래스로 허용되는 유일한 Shape 클래스들은 Circle, Rectangle 및 Square 입니다.
# Java 16
- Pattern Matching for instanceof
- Unix-Domain Socket Channels
- Foreign Linker API - Preview
- Records & Pattern Matching
# Unix-Domain Socket Channels
- 이제 Unix 도메인 소켓에 연결할 수 있습니다(macOS 및 Windows(10+)에서도 지원됨).
socket.connect(UnixDomainSocketAddress.of("/var/run/postgresql/.s.PGSQL.5432"));
# Foreign Linker API - Preview
- JNI(Java Native Interface)에 대한 계획된 교체로, 기본 라이브러리에 바인딩할 수 있습니다.
# Java 17
Java 17은 Java 11 이후의 새로운 Java LTS(장기 지원) 릴리스
- Pattern Matching for switch (Preview)
- Sealed Classes (Finalized)
- Foreign Function & Memory API (Incubator)
- Deprecating the Security Manager
# Pattern Matching for switch (Preview)
- 이제 객체를 전달하여 기능을 전환하고 특정 유형을 확인할 수 있습니다.
public String test(Object obj) {
return switch(obj) {
case Integer i -> "An integer";
case String s -> "A string";
case Cat c -> "A Cat";
default -> "I don't know what it is";
};
}
# Sealed Classes (Finalized)
- Java 15에서 preview 제공되었던 기능 완료
# Foreign Function & Memory API (Incubator)
- Java Native Interface(JNI)를 대체합니다.
- 기본 함수를 호출하고 JVM 외부의 메모리에 액세스할 수 있습니다.