반응형

1. JEP(JDK Enhancement Proposal) 목록

1.1 항상 엄격한 부동 소수점 (JEP 306)

이 JEP는 주로 과학 어플리케이션을 위한 것으로 부동 소수점 연산을 일관성 있게 엄격하게 만든다. 기본 부동 소수점 연산은 strict이거나 strictfp이며, 이 둘은 모든 플랫폼에서 부동 소수점 연산으로부터 동일한 결과를 보장한다.

자바 1.2 이전에는 strictfp 동작도 기본이었다. 하지만 하드웨어 문제로 인해 아키텍처가 바뀌었고 strictfp라는 키워드는 그러한 동작을 다시 활성화하기 위해 필요했다. 이제 더 이상 이 키워드를 사용할 필요가 없다.

 

1.2 향상된 Pseudo-Random Number Generators (JEP 356)

더 특별한 사용 사례와 관련된 JEP 356은 Pseudo-Random Number Generators(PRNG)를 위한 새로운 인터페이스 및 구현을 제공한다. 따라서 다양한 알고리즘을 상호 교환하여 사용하는 것이 더 쉽고 스트림 기반 프로그래밍에 대한 더 나은 지원을 제공한다.

public IntStream getPseudoInts(String algorithm, int streamSize) {
    // returns an IntStream with size @streamSize of random numbers generated using the @algorithm
    // where the lower bound is 0 and the upper is 100 (exclusive)
    return RandomGeneratorFactory.of(algorithm)
            .create()
            .ints(streamSize, 0,100);
}

 

java.util.Random, SplittableRandom and SecureRandom와 같은 레거시 random 클래스들은 이제 새로운 RandomGenerator 인터페이스를 구현한다.

 

1.3 새로운 macOS 렌더링 파이프라인 (JEP 382)

이 JEP는 애플이 Swing GUI에서 내부적으로 사용되는 OpenGL API (macOS 10.14)를 deprecate 처리 했기 때문에, macOS용 자바 2D 내부 렌더링 파이프라인을 제공한다. 새로운 구현은 애플 메탈 API를 사용하며 내부 엔진을 제외하고는 기존 API에 변경 사항이 없다.

 

1.4 macOS/AArch64 Port (JEP 391)

애플은 자사의 컴퓨터 라인을 X64에서 AArch64로 전환하는 장기 계획을 발표했다. 이 JEP는 맥OS 플랫폼에서 AArch64에서 실행되도록 JDK를 포팅한다.

 

1.5 Deprecate the Applet API for Removal (JEP 398)

Applet API를 이용해 개발 경력을 시작한 많은 자바 개발자들에게 이것은 슬플지 모르지만, 많은 웹 브라우저들은 이미 자바 플러그인에 대한 지원을 없앴다. API가 관련성이 없어지자, Java 9에 Deprecate되었던 이 API에 대한 for removal = true 표시를 했다.

 

1.6 강하게 캡슐화된 JDK Internals (JEP 403)

JEP 403은 –illegal-access

flag를 제거함으로써 JDK internals를 강하게 캡슐화하는데 한 단계 더 나아갔다. 플랫폼은 이 flag를 무시할 것이고, 만약 이 flag 값이 존재한다면 콘솔은 이 flag에 대한 사용 중단에 대한 메세지를 발행할 것이다.이 기능은 sun.misc.Unsafe와 같은 중요한 API를 제외하고 JDK internals에 사용자가 접근하는 것을 방지한다.

 

1.7 Switch 구문에 대한 패턴 매칭 (Preview) (JEP 406)

스위치 구문에 대한 패턴 매칭 기능이 추가되었다. 이로써 보일러플레이트 코드가 줄고 언어의 표현성이 향상되었다.

아래 예시를 통해 이해를 해보자.

static record Human (String name, int age, String profession) {}

public String checkObject(Object obj) {
    return switch (obj) {
        case Human h -> "Name: %s, age: %s and profession: %s".formatted(h.name(), h.age(), h.profession());
        case Circle c -> "This is a circle";
        case Shape s -> "It is just a shape";
        case null -> "It is null";
        default -> "It is an object";
    };
}

public String checkShape(Shape shape) {
    return switch (shape) {
        case Triangle t && (t.getNumberOfSides() != 3) -> "This is a weird triangle";
        case Circle c && (c.getNumberOfSides() != 0) -> "This is a weird circle";
        default -> "Just a normal shape";
    };
}

 

1.8 RMI Activation 제거 (JEP 407)

Java 15에서 for removal = true로 표시되었던 것이 Java 17에서 제거되었다.

 

1.9 Sealed class (JEP 409)

Java 15, 16에서 Preview 모드였던 Sealed class가 Java 17에서 공식적으로 언어의 새로운 기능이 되었다.

이 기능은 어떠한 클래스나 인터페이스가 이 Sealed class를 상속/구현할지의 여부를 제한한다. 새로운 Switch 구문의 패턴매칭과 함께 사용되면서 더 세련되고 깔끔한 타입 조사와 캐스팅이 가능하게 되었다. 아래 예시를 살펴보자.

int getNumberOfSides(Shape shape) {
    return switch (shape) {
        case WeirdTriangle t -> t.getNumberOfSides();
        case Circle c -> c.getNumberOfSides();
        case Triangle t -> t.getNumberOfSides();
        case Rectangle r -> r.getNumberOfSides();
        case Square s -> s.getNumberOfSides();
    };
}

 

1.10 AOT/JIT 컴파일러 제거 (JEP 410)

실험 기능으로 JDK 9와 JDK 10에 각각 도입된 AOT(Ahead-Of-Time) 컴파일러(JEP 295)와 GraalVM(JEP-317)의 JIT(Just-In-Time) 컴파일러는 유지 보수 비용이 높은 기능이었다.

이들은 별다른 채택을 받지 못했다. 이 때문에 이 JEP는 이들을 플랫폼에서 제외시켰지만, 개발자들은 여전히 그랄VM을 이용해 이들을 활용할 수 있다.

 

1.11 Deprecate the Security Manager for Removal (JEP 411)

Security Manager는 클라이언트 측 자바 코드를 보안하는 것을 목표로 했지만 더 이상 관련성이 없기 때문에 제거하도록 표시되었다.

 

1.12 Foreign Function and Memory API (Incubator) (JEP 412)

Foreign Function and Memory API를 통해 자바 개발자들은 JVM 외부에서 코드에 접근하여 힙 밖으로 메모리를 관리할 수 있다. JNI API를 대체하여 기존보다 보안성과 성능을 향상시키는 것이 목표이다.

이 API는 프로젝트 파나마에 의해 개발된 또 다른 기능이며, JEP 393, 389, 383 및 370에 의해 진화되고 선행되었다.

이 기능을 활용하여 우리는 Java class에서 C 라이브러리를 호출할 수 있다.

 

먼저 API를 통해 호출하고자 하는 라이브러리를 로드할 필요가 있다. 이후에 타겟 메서드 시그니처를 명시하고 호출한다.

public class JEP412 {
    private static final SymbolLookup libLookup;

    static {
        // loads a particular C library
        var path = JEP412.class.getResource("/print_name.so").getPath();
        System.load(path);
        libLookup = SymbolLookup.loaderLookup();
    }
    
    public String getPrintNameFormat(String name) {
        var printMethod = libLookup.lookup("printName");

        if (printMethod.isPresent()) {
            var methodReference = CLinker.getInstance()
                .downcallHandle(
                    printMethod.get(),
                    MethodType.methodType(MemoryAddress.class, MemoryAddress.class),
                    FunctionDescriptor.of(CLinker.C_POINTER, CLinker.C_POINTER)
                );

            try {
                var nativeString = CLinker.toCString(name, ResourceScope.newImplicitScope());
                var invokeReturn = methodReference.invoke(nativeString.address());
                var memoryAddress = (MemoryAddress) invokeReturn;
                return CLinker.toJavaString(memoryAddress);
            } catch (Throwable throwable) {
                throw new RuntimeException(throwable);
            }
        }
        throw new RuntimeException("printName function not found.");
    }
}

 

1.13 Vector API (Second Incubator) (JEP 414)

벡터 API는 병렬로 실행되는 다양한 명령어 집합을 의미하는 SIMD(Single Instruction, Multiple Data) 유형의 연산을 다룬다. 벡터 명령어를 지원하고 파이프라인과 같은 명령어의 실행을 허용하는 특수 CPU 하드웨어를 활용한다.
결과적으로, 새로운 API는 개발자들이 기본 하드웨어의 잠재력을 활용하여 보다 효율적인 코드를 구현할 수 있게 해줄 것이다.
이 연산에 대한 일상적인 사용 사례는 과학 대수 선형 응용, 이미지 처리, 문자 처리, 및 임의의 무거운 산술 응용 또는 다수의 독립 피연산자에 대한 연산을 적용해야 하는 임의의 응용이다.
API를 사용하여 간단한 벡터 곱셈 예를 설명해 보자

public void newVectorComputation(float[] a, float[] b, float[] c) {
    for (var i = 0; i < a.length; i += SPECIES.length()) {
        var m = SPECIES.indexInRange(i, a.length);
        var va = FloatVector.fromArray(SPECIES, a, i, m);
        var vb = FloatVector.fromArray(SPECIES, b, i, m);
        var vc = va.mul(vb);
        vc.intoArray(c, i, m);
    }
}

public void commonVectorComputation(float[] a, float[] b, float[] c) {
    for (var i = 0; i < a.length; i ++) {
        c[i] = a[i] * b[i];
    }
}

 

1.14 컨텍스트-특정적 역직렬화 필터 (JEP 415)

Java 9에 처음 도입된 JEP 290은 많은 보안 문제의 공통 소스인 신뢰할 수 없는 소스로부터 들어오는 직렬화된 데이터를 검증할 수 있게 해주었다. 그 검증은 JVM 레벨에서 이루어지며, 더 많은 보안과 견고성을 제공한다.
JEP 415로, 애플리케이션들은 JVM 레벨에서 정의된 컨텍스트-특정적이고 동적으로 선택된 병렬화 필터들을 구성할 수 있다. 각각의 병렬화 동작은 그러한 필터들을 호출할 것이다.

 

 

※ 참조

https://www.baeldung.com/java-17-new-features

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 16의 새로운 기능  (2) 2024.06.10
Java 15의 새로운 기능  (0) 2024.06.09
Java 14의 새로운 기능  (0) 2024.06.07
Java 13의 새로운 기능  (1) 2024.06.06
Java 12의 새로운 기능  (0) 2024.06.05
반응형

1. Proxy 객체에서 default 메서드 호출

Java 16에서는 인터페이스의 default 메서드에 대한 개선된 기능으로 java.lang.reflect.InvocationHandler는 리플렉션을 사용하여 동적 프록시를 통해 인터페이스의 default 메서드를 호출한다.

아래에 간단한 예시를 살펴보자.

interface HelloWorld {
    default String hello() {
        return "world";
    }
}

 

이제 우리는 reflection을 사용하여 이 인터페이스의 프록시에 대한 default 메서드를 호출할 수 있다.

Object proxy = Proxy.newProxyInstance(getSystemClassLoader(), new Class<?>[] { HelloWorld.class },
    (prox, method, args) -> {
        if (method.isDefault()) {
            return InvocationHandler.invokeDefault(prox, method, args);
        }
        // ...
    }
);
Method method = proxy.getClass().getMethod("hello");
assertThat(method.invoke(proxy)).isEqualTo("world");

 

2. 새로운 시간 Symbol

DateTimeFormatter에 am/pm에 대한 대체 표현을 제공하는 새로운 symbol인 " B"가 추가되었다.

LocalTime date = LocalTime.parse("15:25:08.690791");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("h B");
assertThat(date.format(formatter)).isEqualTo("3 in the afternoon");

 

우리는 "3 pm" 대신 "3 in the afternoon"을 출력값으로 얻을 수 있다. 또한 우리는 " B", " BBBB", " BBBBB" 등의 패턴을 통해 짧거나 전체로 이뤄진 스타일을 적용할 수 있다.

 

3. Stream.toList 메서드

Collectors.toList와 Collectors.toSet과 같은 Stream Collector로 이뤄진 보일러플레이트 코드들을 줄이기 위해 Stream.toList 메서드가 추가되었다. 아래 예시를 살펴보자.

List<String> integersAsString = Arrays.asList("1", "2", "3");
List<Integer> ints = integersAsString.stream().map(Integer::parseInt).collect(Collectors.toList());
List<Integer> intsEquivalent = integersAsString.stream().map(Integer::parseInt).toList();

 

예시에서 ints와 intsEquivalent는 동일한 결과 값을 가진다.

 

4. Vector API (인큐베이션 단계)

Java 16에서 Vector API는 초기 인큐베이션 단계에 있다. 이 API의 목적은 전통적인 스칼라 계산보다 최적화된 퍼포먼스를 내기 위해, 벡터 계산을 제공하는 것이다.

먼저 전통적인 방법으로 두 배열을 곱하는 예시를 살펴보자.

int[] a = {1, 2, 3, 4};
int[] b = {5, 6, 7, 8};

var c = new int[a.length];

for (int i = 0; i < a.length; i++) {
    c[i] = a[i] * b[i];
}

 

이 예시에서는 배열의 길이에 해당하는 4번의 cycle이 실행될 것이다. 이제 벡터 기반의 계산을 사용한 예시를 보자.

int[] a = {1, 2, 3, 4};
int[] b = {5, 6, 7, 8};

var vectorA = IntVector.fromArray(IntVector.SPECIES_128, a, 0);
var vectorB = IntVector.fromArray(IntVector.SPECIES_128, b, 0);
var vectorC = vectorA.mul(vectorB);
vectorC.intoArray(c, 0);

 

위 예시에서 우리가 처음으로 한 것은 fromArray 메서드를 통해 배열로부터 2개의 IntVector를 생성한 것이다. 메서드의 첫번째 파라미터는 벡터의 사이즈에 해당하고, 그 다음 파라미터는 배열, 그 다음은 offset 값이다. 여기서 가장 중요한 것은 벡터의 사이즈를 128 bit로 설정했다는 것이다. Java에서 각각의 int 값은 4 byte에 해당한다. 이 예시에서는 4개의 int를 가진 배열이 나오기 때문에, 이것을 저장하기 위해서는 128(4 X 8 X 4) bit가 필요하다. 여기서 단일 벡터는 전체 배열을 저장할 수 있다.

특정 아키텍처에서 컴파일러는 바이트 코드를 최적화하여 계산 과정을 4 -> 1 cycle로 줄일 수 있을 것이다. 이러한 최적화는 머신 러닝이나 암호화 프로세스에 유리하다.

Vector API는 인큐베이션 단계에 있는 것이기 때문에 Java의 새로운 릴리즈에서는 변경될 수 있다는 것을 기억해야 한다.

 

5. Record

Record는 Java 14에서 처음 소개되었다. Java 16은 여기에 점증적인 변화를 가져왔다.

Record는 제한된 class의 형태라는 점에서 enum과 비슷하다. Record를 정의하는 것은 불변 데이터 객체를 정의하는 간결한 방법이다.

 

5.1 Record가 없을 때

아래 예시에서 Book class를 정의해보자.

public final class Book {
    private final String title;
    private final String author;
    private final String isbn;

    public Book(String title, String author, String isbn) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public String getIsbn() {
        return isbn;
    }

    @Override
    public boolean equals(Object o) {
        // ...
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, author, isbn);
    }
}

 

Java에서 간단한 데이터 객체를 생성하는데는 많은 보일러플레이트 코드들이 필요하다. 이것은 다루기 번거롭고 때때로 개발자들이 equals와 hashCode와 같은 메서드들을 오버라이드하지 않아 버그를 발생시키기도 한다.

대부분의 요즘 IDE들은 getter, setter, 생성자 등과 같은 코드들에 대한 자동 생성 기능을 제공한다. 이것은 위에서 말했던 문제들을 경감시키고 개발자들의 부담을 덜어준다. 그러나 Record는 이러한 보일러플레이트 코드들 없이 똑같은 결과를 만들어 낸다.

 

5.2 Record가 있을 때

아래에 Record를 이용해서 다시 작성된 Book class를 보자.

public record Book(String title, String author, String isbn) {
}

 

record 키워드를 사용함으로써 Book class의 코드는 2줄로 줄어들었다. 이것은 훨씬 쉽고 에러가 발생시킬 확률이 적다.

 

5.3 Record에 대한 추가 사항

Java 16에서는 inner class의 멤버변수로 record를 사용하는 것이 가능하다.

class OuterClass {
    class InnerClass {
        Book book = new Book("Title", "author", "isbn");
    }
}

 

6. instanceof에 대한 패턴 매칭

instanceof에 대한 패턴 매칭은 Java 12에서 Preview 모드로 처음 소개되었다. Java 16에서 프로덕션 레벨로 올라온 것으로 보인다.

패턴 매칭이 없는 코드 예시는 아래와 같다.

Object obj = "TEST";

if (obj instanceof String) {
    String t = (String) obj;
    // do some logic...
}

 

패턴 매칭을 사용하여 아래와 같이 코드를 다시 작성할 수 있다.

Object obj = "TEST";

if (obj instanceof String t) {
    // do some logic
}

 

우리는 이제 instanceof check 과정의 일부로 변수(여기서는 t)를 선언할 수 있다.

 

7. Sealed class (Preview)

7.1 예제

인터페이스와 이를 구현하는 2개의 클래스를 예시로 살펴보자.

public sealed interface JungleAnimal permits Monkey, Snake  {
}

public final class Monkey implements JungleAnimal {
}

public non-sealed class Snake implements JungleAnimal {
}

 

sealed 키워드는 permits 키워드와 함께 사용되었는데, 이는 어떤 class들이 이 인터페이스를 구현하도록 허락되었는지를 결정해준다. 이 예제에서는 Monkey와 Snake이다.

sealed class의 모든 자식 class들은 반드시 아래의 것들 중 하나로 표시되어야 한다.

1) sealed : 어떤 class가 이 class를 상속하도록 허락되었는지를 permits 키워드를 사용하여 나타내야한다는 의미이다.

2) final : 추가적인 자식 class가 없다는 뜻이다.

3) non-sealed : 이 class는 어떤 클래스도 상속이 가능하다는 의미이다.

 

sealed class의 가장 큰 이점은 모든 경우의 수를 커버할 필요가 있는 패턴 매칭 체크를 완벽하게 해낼 수 있다는 것이다. 위에서 정의한 class로 예를 들면, 우리는 JungleAnimal의 자식 클래스에 대한 모든 가능한 경우를 커버할 수 있다.

JungleAnimal j = // some JungleAnimal instance

if (j instanceof Monkey m) {
    // do logic
} else if (j instanceof Snake s) {
    // do logic
}

 

여기서 sealed class는 오직 Monkey와 Snake만 자식 클래스로 허용하기 때문에, 추가적인 else 구문이 필요가 없다.

 

 

※ 참조

https://www.baeldung.com/java-16-new-features

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 17의 새로운 기능  (1) 2024.06.16
Java 15의 새로운 기능  (0) 2024.06.09
Java 14의 새로운 기능  (0) 2024.06.07
Java 13의 새로운 기능  (1) 2024.06.06
Java 12의 새로운 기능  (0) 2024.06.05
반응형

1. Record (Preview)

record는 불변 데이터 객체를 더 쉽게 생성할 수 있게 해주는 새로운 타입의 자바 class이다.

Java 14에서 Preview모드로 소개되었으며, Java 15에서는 공식 Production 기능이 되기 전, 몇 가지를 더 개선하는 것을 목표로 하고 있다.

 

1.1 Record가 없을 때

record가 생기기 전에는 불변 데이터 전송 객체(DTO)를 다음과 같이 생성했을 것이다.

public class Person {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

 

상태를 유지하는 불변 객체를 생성하기 위해 위와 같은 많은 코드가 필요하다. 모든 필드들은 명시적으로 final로 지정되어있고, 모든 필드를 파라미터로 가지는 한 개의 생성자를 가지고 있다. 또한 모든 필드들에 대한 getter가 있다. 때때로 우리는 subclass 생성을 막기 위해 class 자체를 final로 선언해야 한다.

대부분의 상황에서 우리는 한 단계 더 나아가 의미있는 로그를 출력하기 위해 toString() 메서드를 오버라이드한다. 또한 아마도 우리는 2개의 객체를 비교할 때 예측하지 못한 결과를 초래하지 않기 위해 equals()와 hashCode()메서드를 오버라이드 해야할 것이다.

 

1.2 Record를 사용할 때

record class를 사용함으로써, 우리는 똑같은 불변 객체를 훨씬 더 간편한 방법으로 정의할 수 있다.

public record Person(String name, int age) {
}

 

 

맨 앞에 위치한 class 정의는 Record에 대한 새로운 syntax이다. 이것은 record내의 필드들에 대한 정보를 제공한다.

또한 이를 통해 컴파일러는 class 내부의 필드를 추론할 수 있다. 이를 통해 우리는 멤버 변수나 getter와 같은 것들을 따로 정의할 필요가 없다. 또한 생성자도 정의할 필요가 없다.

게다가 컴파일러는 toString(), equals(), hashCode()에 대한 오버라이드된 메서드를 제공한다.

이처럼 record가 많은 보일러플레이트 코드를 삭제해주는 반면, 디폴트 동작을 오버라이드하는 것도 가능하다. 예를 들면 다음과 같이 생성자 내에 유효성 검사를 추가하는 것이 가능하다.

public record Person(String name, int age) {
    public Person {
        if(age < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
    }
}

 

record들은 언제나 final이다. 그러므로 abstact로 선언되거나 native 메서드를 사용할 수 없다.

 

2. Sealed Class (Preview)

Sealed class는 어떤 타입이 subclass로서 사용되는 것이 가능한지를 나타낼 수 있다. 이것은 인터페이스에도 적용되어 어떤 타입이 그것을 구현할 수 있을지를 결정할 수 있다.

Sealed class는 2가지 키워드로 구성된다. - sealed, permits

public abstract sealed class Person permits Employee, Manager {
    //...
}

 

위의 예제에서 우리는 Person이라는 class를 abstract로 선언하였다. 그리고 우리는 오직 Employee, Manager class만이 Person class를 상속하는 것이 가능하다는 것을 명시하였다. 아래는 Person class를 상속한 예시이다.

public final class Employee extends Person {
}

public non-sealed class Manager extends Person {
}

 

sealed class를 상속하는 class는 반드시 sealed나 non-sealed 혹은 final로 선언되어야 한다. 이것은 class의 계층구조를 유한하게 유지시켜 준다.

이 유한한 계층구조는 sealed class를 사용하는 장점 중의 하나이다. 아래 예시를 보자.

if (person instanceof Employee) {
    return ((Employee) person).getEmployeeId();
} 
else if (person instanceof Manager) {
    return ((Manager) person).getSupervisorId();
}

 

sealed class가 없다면, 컴파일러는 모든 subclass가 커버되었는지를 if-else문을 통해 알 수 없을 것이다. 컴파일러는 else 구문이 없다면, 이 로직이 모든 케이스를 커버하지 못한다는 경고를 할 것이다.

 

3. 기타 변경 사항

Java 15에서는 Java 13과 14에서 Preview 모드로 제공되었던 텍스트 블록이 Production 기능으로 제공된다.

또한 Java 14에서 제공되었던 유용한 NullpointerException 기능이 디폴트로 제공된다.

 

 

※ 참조

https://www.baeldung.com/java-15-new

 

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 17의 새로운 기능  (1) 2024.06.16
Java 16의 새로운 기능  (2) 2024.06.10
Java 14의 새로운 기능  (0) 2024.06.07
Java 13의 새로운 기능  (1) 2024.06.06
Java 12의 새로운 기능  (0) 2024.06.05
반응형

1. 이전 버전에서 넘어온 기능들

1.1 Switch 구문

새로운 Switch 구문은 Java 12, 13에서 Preview 모드로 제공되었다. 그러나 이제 새로운 Switch 구문은 표준화되어 정식으로 JDK에 포함되어졌다. 이것이 의미하는 건, 이제 이 기능을 Preview 모드에서 뿐만 아니라 Production 코드에서도 사용할 수 있다는 것이다.

간단한 예시를 살펴보자. 아래 코드는 새로운 Switch 구문이 생기기 전에 작성된 코드이다.

boolean isTodayHoliday;
switch (day) {
    case "MONDAY":
    case "TUESDAY":
    case "WEDNESDAY":
    case "THURSDAY":
    case "FRIDAY":
        isTodayHoliday = false;
        break;
    case "SATURDAY":
    case "SUNDAY":
        isTodayHoliday = true;
        break;
    default:
        throw new IllegalArgumentException("What's a " + day);
}

 

이제 새로운 Switch 구문을 써보자

boolean isTodayHoliday = switch (day) {
    case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> false;
    case "SATURDAY", "SUNDAY" -> true;
    default -> throw new IllegalArgumentException("What's a " + day);
};

 

1.2 텍스트 블록 (Preview)

텍스트 블록은 여전히 메인스트림의 업그레이드가 되기위한 여정 위에 있다. 여전히 Preview 모드로 제공된다.

멀티 라인 문자열을 쓰기 쉽게된 Java 13에서의 기능에 더해, 텍스트 블록은 이제 2가지 새로운 이스케이프 시퀀스를 갖는다.

1) \: 줄의 마지막임을 나타내지만 개행 문자는 추가되지 않는다.
2) \s: 싱글 스페이스를 나타낸다.

 

아래의 예시를 보자.

String multiline = "A quick brown fox jumps over a lazy dog; the lazy dog howls loudly.";

 

이게 아래처럼 쓰여질 수 있다.

String multiline = """
    A quick brown fox jumps over a lazy dog; \
    the lazy dog howls loudly.""";

 

2. 새로운 Preview 기능

2.1 Record (Preview)

Data 모델에서의 반복되는 보일러플레이트 코드를 제거하기 위해 Record라는 것이 소개되었다. 이것은 일상의 개발을 단순화하고 효율성을 높이며 휴먼 에러의 위험성을 최소화해준다.

예를 들면, id와 password를 가지고 있는 User라는 data 모델은 아래와 같이 단순히 정의할 수 있다.

public record User(int id, String password) { };

 

우리는 새로운 키워드인 record를 사용할 수 있다. 이 간단한 선언은 자동으로 생성자, getter, equals, hashCode, toString 메서드를 추가해준다.

JUnit 테스트에서 이 예시를 더 자세히 살펴보자.

private User user1 = new User(0, "UserOne");

@Test
public void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters() {
    assertEquals(0, user1.id());
    assertEquals("UserOne", user1.password());
}

@Test
public void whenRecord_thenEqualsImplemented() {
    User user2 = user1;
    assertEquals(user1, user2);
}

@Test
public void whenRecord_thenToStringImplemented() {
    assertTrue(user1.toString().contains("UserOne"));
}

 

3. 새로운 Production 기능

3.1 도움을 주는 NullPointerException

이전까지 NullPointerException의 stack trace는 주어진 파일의 주어진 라인에서 Null이 발생했다는 정보 이외에는 특별한 정보를 주지 못했다.

이제 Java는 주어진 라인에서 무엇이 정확히 Null인지를 짚어주게되었다.

아래 간단한 예시를 살펴보자.

int[] arr = null;
arr[0] = 1;

 

이전 버전에서 이 코드를 실행했을 경우, 로그는 아래와 같이 나타났다.

Exception in thread "main" java.lang.NullPointerException
at com.baeldung.MyClass.main(MyClass.java:27)

 

그러나 이제는 아래와 같이 로그가 나타난다.

java.lang.NullPointerException: Cannot store to int array because "arr" is null

 

 

※ 참조

https://www.baeldung.com/java-14-new-features

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 16의 새로운 기능  (2) 2024.06.10
Java 15의 새로운 기능  (0) 2024.06.09
Java 13의 새로운 기능  (1) 2024.06.06
Java 12의 새로운 기능  (0) 2024.06.05
Java 11의 새로운 기능  (0) 2024.06.04
반응형

1. Preview 기능

비록 Preview 모드이지만, Java 13dms 2가지 새로운 기능을 제공한다. 이것들은 피드백에 따라 제거될 수도 있고 영원히 반영될 수도 있다. Preview 기능들을 사용하기 위해서는 커멘드 라인에 -enable-preview를 명시해야 한다.

 

1.1 Switch 구문 (Preview)

우리는 새로운 Switch 구문에 대해 Java 12에서 이미 본 적이 있다. Java 13에서는 yield 구문이 추가되었다.

yield를 사용함으로써, 우리는 switch 구문에서 값을 효과적으로 반환할 수 있다.

@Test
@SuppressWarnings("preview")
public void whenSwitchingOnOperationSquareMe_thenWillReturnSquare() {
    var me = 4;
    var operation = "squareMe";
    var result = switch (operation) {
        case "doubleMe" -> {
            yield me * 2;
        }
        case "squareMe" -> {
            yield me * me;
        }
        default -> me;
    };

    assertEquals(16, result);
}

 

1.2 텍스트 블록 (Preview)

두 번째 Preview 기능은 JSON, XML, HTML과 같은 멀티 라인 String에 대한 텍스트 블록이다.

이전 버전에서는 JSON을 아래와 같이 선언해야 했다.

String JSON_STRING 
  = "{\r\n" + "\"name\" : \"Baeldung\",\r\n" + "\"website\" : \"https://www.%s.com/\"\r\n" + "}";

 

이제 텍스트 블록을 사용하여 아래와 같이 선언할 수 있다.

String TEXT_BLOCK_JSON = """
{
    "name" : "Baeldung",
    "website" : "https://www.%s.com/"
}
""";

 

예시에서 볼 수 있듯이, 쌍따옴표나 개행문자를 위해 이스케이프 문자를 사용할 필요가 없다. 텍스트 블록을 사용함으로써, JSON과 같은 멀티 라인 String을 더 쉽게 쓰고 읽을 수 있게 되었다.

 

아래와 같이 텍스트 블록에 대해 모든 String 메서드들을 사용하는 것이 가능하다.

@Test
public void whenTextBlocks_thenStringOperationsWorkSame() {        
    assertThat(TEXT_BLOCK_JSON.contains("Baeldung")).isTrue();
    assertThat(TEXT_BLOCK_JSON.indexOf("www")).isGreaterThan(0);
    assertThat(TEXT_BLOCK_JSON.length()).isGreaterThan(0);
}

 

또한 String class는 텍스트 블록을 다루기 위한 3가지 새로운 메서드를 제공한다.

1) stripIndent() – 부수적인 white space를 제거한다.
2) translateEscapes() – 이스케이프 문자를 해석한다. (예 : “\\t” -> “\t”)
3) formatted() – String::format 메서드와 동일하게 동작하지만 텍스트 블록을 위한 메서드이다.

 

아래는 formatted() 메서드에 대한 예시이다.

assertThat(TEXT_BLOCK_JSON.formatted("baeldung").contains("www.baeldung.com")).isTrue();
assertThat(String.format(JSON_STRING,"baeldung").contains("www.baeldung.com")).isTrue();

 

2. 레거시 Socket API에 대한 재구현

Socket API(java.net.Socket, java.net.ServerSocket)은 자바에 내장된 부분으로써 사용되어져 왔다. 그러나 이것들은 지난 20년간 최적화되지 않았다. 레거시 자바로 쓰여진 코드들은 다루기 힘들고 유지보수하기 어렵다.

Java 13은 API를 미래 지향적인 사용자 모드 스레드에 맞게 기본 구현을 대체했다. PlainSocketImpl 대신에 이제 NioSocketImpl를 제공한다. 새롭게 작성된 코드는 java.nio와 같은 내부 인프라스트럭처를 기반으로 한다.

물론 PlainSocketImpl를 다시 사용하는 것도 가능하다. JVM의 시스템 프로퍼티 Djdk.net.usePlainSocketImpl를 true로 주면된다. 디폴트는 NioSocketImpl이다.

 

 

※ 참조

https://www.baeldung.com/java-13-new-features

 

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 15의 새로운 기능  (0) 2024.06.09
Java 14의 새로운 기능  (0) 2024.06.07
Java 12의 새로운 기능  (0) 2024.06.05
Java 11의 새로운 기능  (0) 2024.06.04
Java 10의 새로운 기능 - 기타  (0) 2021.10.07
반응형

1. 새로운 기능들

1.1 String class의 새로운 메서드

Java 12는 String class에서 2가지 새로운 메서드를 제공한다.

 

1) indent

정수 파라미터를 바탕으로 각 라인의 들여쓰기를 조정하는 메서드이다. 만약 파라미터 값이 0보다 크면, 새로운 space가 각 라인 앞에 삽입된다. 반면 파라미터 값이 0보다 작으면, 각각의 라인 앞의 space를 제거한다. 만약 주어진 라인이 충분한 white space를 가지고 있지 않다면, 모든 white space가 제거된다.

간단한 예시를 살펴보자. 먼저 4 space로 들여쓰기를 추가하고, 모든 들여쓰기를 제거할 것이다.

String text = "Hello Baeldung!\nThis is Java 12 article.";

text = text.indent(4);
System.out.println(text);

text = text.indent(-10);
System.out.println(text);

 

출력 값은 다음과 같다.

    Hello Baeldung!
    This is Java 12 article.

Hello Baeldung!
This is Java 12 article.

 

들여쓰기 값을 초과하는 -10이라는 값을 넘겼음에도 불구하고, 문자는 영향을 받지 않고 오직 space만 제거되었다.

 

2) transform

이 메서드는 단일 인자 function을 파라미터로 받는다. 이 function은 string에 적용된다.

문자열의 앞뒤를 뒤바꾸는 다음 예시를 살펴보자.

@Test
public void givenString_thenRevertValue() {
    String text = "Baeldung";
    String transformed = text.transform(value ->
      new StringBuilder(value).reverse().toString()
    );

    assertEquals("gnudleaB", transformed);
}

 

1.2 File의 mismatch 메서드

public static long mismatch(Path path, Path path2) throws IOException

 

이 메서드는 두 파일을 비교하고 그들의 내용 중 처음으로 mismatch되는 곳의 위치를 반환한다.

반환 값은 0부터 더 작은 파일의 byte 사이즈가 될 것이며, 두 파일이 동일할 경우 -1을 반환한다.

동일한 2개의 파일을 비교해서 반환 값이 -1이 되는 다음 예시를 살펴보자.

@Test
public void givenIdenticalFiles_thenShouldNotFindMismatch() {
    Path filePath1 = Files.createTempFile("file1", ".txt");
    Path filePath2 = Files.createTempFile("file2", ".txt");
    Files.writeString(filePath1, "Java 12 Article");
    Files.writeString(filePath2, "Java 12 Article");

    long mismatch = Files.mismatch(filePath1, filePath2);
    assertEquals(-1, mismatch);
}

 

2번째 예시는 두 파일이 다른 내용을 가지고 mismatch되는 위치가 8을 리턴한다.

@Test
public void givenDifferentFiles_thenShouldFindMismatch() {
    Path filePath3 = Files.createTempFile("file3", ".txt");
    Path filePath4 = Files.createTempFile("file4", ".txt");
    Files.writeString(filePath3, "Java 12 Article");
    Files.writeString(filePath4, "Java 12 Tutorial");

    long mismatch = Files.mismatch(filePath3, filePath4);
    assertEquals(8, mismatch);
}

 

1.3 Teeing Collector

Java 12에서는 Collectors class에 teeing collector가 추가되었다.

Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,
  Collector<? super T, ?, R2> downstream2, BiFunction<? super R1, ? super R2, R> merger)

 

이것은 두 downstream collector의 합성물이다. 모든 요소들은 2개의 downstream collector에 의해 처리된다. 그런 다음 그들의 결과값은 merge function으로 넘어가서 최종 결과물로 변환된다.

다음은 숫자들의 평균값을 계산하는 teeing collector의 사용 예시이다. 첫번째 collector는 파라미터들의 값을 모두 더한다. 그리고 두번째 collector는 파라미터들의 갯수를 제공한다. 마지막으로 merge function은 이 두 값을 이용하여 평균값을 계산한다.

@Test
public void givenSetOfNumbers_thenCalculateAverage() {
    double mean = Stream.of(1, 2, 3, 4, 5)
      .collect(Collectors.teeing(Collectors.summingDouble(i -> i), 
        Collectors.counting(), (sum, count) -> sum / count));
    assertEquals(3.0, mean);
}

 

1.4 Compact Number Formatting

Java 12는 CompactNumberFormat이라는 새로운 Number format을 제공한다. 이것은 숫자들을 더 짧은 형태로 나타내기 위해 디자인되었다. 이 패턴들은 주어진 locale을 기반으로 제공된다.

우리는 NumberFormat class의 getCompactNumberInstance 메서드를 통해 객체를 얻을 수 있다.

public static NumberFormat getCompactNumberInstance(Locale locale, NumberFormat.Style formatStyle)

 

이전에 언급했던 것 처럼, locale 파라미터에 따라 적절한 format 패턴이 결정된다. format 스타일은 SHORT, LONG으로 정해질 수 있다. 예를 들어 1000이라는 숫자를 US locale로 생각해보자. SHORT 스타일은 '10K'가 될 것이고, LONG 스타일은 '10 thousand'가 될 것이다.

@Test
public void givenNumber_thenCompactValues() {
    NumberFormat likesShort = 
      NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT);
    likesShort.setMaximumFractionDigits(2);
    assertEquals("2.59K", likesShort.format(2592));

    NumberFormat likesLong = 
      NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
    likesLong.setMaximumFractionDigits(2);
    assertEquals("2.59 thousand", likesLong.format(2592));
}

 

 

2. Preview Changes

새로운 기능들 중 일부는 오직 Preview로만 제공된다. 이것들을 활성화하기 위해서, 우리는 IDE 상의 적절한 세팅 값을 바꾸거나 컴파일러에 옵션값을 다음과 같이 줘야한다.

javac -Xlint:preview --enable-preview -source 12 src/main/java/File.java

 

2.1 Switch 표현식 (Preview)

이전 구문과 새로운 구문을 비교해보자. 먼저 이전 구문이다.

DayOfWeek dayOfWeek = LocalDate.now().getDayOfWeek();
String typeOfDay = "";
switch (dayOfWeek) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        typeOfDay = "Working Day";
        break;
    case SATURDAY:
    case SUNDAY:
        typeOfDay = "Day Off";
}

 

이번에는 새로운 구문이다.

typeOfDay = switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Working Day";
    case SATURDAY, SUNDAY -> "Day Off";
};

 

새로운 switch 구문이 더 compact하고 가독성이 좋다. 또 다른 차이점은 switch 구문을 통해 변수에 직접적으로 값을 할당하는 것이 가능해졌다는 것이다. 물론 반환 값이 없는 switch 구문도 가능하다.

switch (dayOfWeek) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> System.out.println("Working Day");
    case SATURDAY, SUNDAY -> System.out.println("Day Off");
}

 

복잡한 로직을 작성하기 위해서는 중괄호를 활용하면 된다.

case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> {
    // more logic
    System.out.println("Working Day")
}

 

 

2.2 instanceof의 패턴 매칭 (Preview)

이전 자바 버전에서는 instanceof를 통해 클래스가 확인되었다고 하더라도, 명시적으로 타입 캐스팅을 아래와 같이 해줘야 했다.

Object obj = "Hello World!";
if (obj instanceof String) {
    String s = (String) obj;
    int length = s.length();
}

 

자바 12에서는 새로운 타입 캐스팅이 된 변수를 아래와 같이 다이렉트로 선언할 수 있다.

if (obj instanceof String s) {
    int length = s.length();
}

 

 

※ 참조

https://www.baeldung.com/java-12-new-features

반응형

'Java의 새로운 기능' 카테고리의 다른 글

Java 14의 새로운 기능  (0) 2024.06.07
Java 13의 새로운 기능  (1) 2024.06.06
Java 11의 새로운 기능  (0) 2024.06.04
Java 10의 새로운 기능 - 기타  (0) 2021.10.07
Java 10의 새로운 기능 - 성능 향상  (0) 2021.09.24
반응형

1. Oracle vs. Open JDK

Java 10은 라이센스 없이 상업적으로 사용할 수 있는 오라클의 마지막 무료 배포 버전이었다. Java 11부터 무료 LTS(long-term support) 버전은 더 이상 제공되지 않는다.

대신에 오라클은 무료로 사용할 수 있는 Open JDK 를 계속해서 제공한다. 오라클 뿐만 아니라, 다른 Open JDK providers 들도 고려해볼 수 있다.

 

2. 개발자들에게 유용한 기능

2.1 새로운 String 메서드

Java 11은 String class에 몇몇 새로운 메서드들을 추가하였다. : isBlank, lines, strip, stripLeading, stripTrailing, repeat

아래는 사용 예시이다.

String multilineString = "Baeldung helps \n \n developers \n explore Java.";
List<String> lines = multilineString.lines()
  .filter(line -> !line.isBlank())
  .map(String::strip)
  .collect(Collectors.toList());
assertThat(lines).containsExactly("Baeldung helps", "developers", "explore Java.");

 

2.2 새로운 File 메서드

파일의 문자열들을 읽고 쓰는 것이 더 쉬워졌다. Files class의 readString, writeString static 메서드를 사용할 수 있다.

Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo", ".txt"), "Sample text");
String fileContent = Files.readString(filePath);
assertThat(fileContent).isEqualTo("Sample text");

 

2.3 Collection 에서 배열로

java.util.Collection 인터페이스는 IntFunction 인자를 받는 toArray default 메서드를 포함하게 되었다.

List sampleList = Arrays.asList("Java", "Kotlin");
String[] sampleArray = sampleList.toArray(String[]::new);
assertThat(sampleArray).containsExactly("Java", "Kotlin");

 

2.4 Not Predicate 메서드

Predicate 인터페이스에 not 메서드가 추가되었다. 이것을 활용하여 존재하는 Predicate을 무효화할 수 있다.

List<String> sampleList = Arrays.asList("Java", "\n \n", "Kotlin", " ");
List withoutBlanks = sampleList.stream()
  .filter(Predicate.not(String::isBlank))
  .collect(Collectors.toList());
assertThat(withoutBlanks).containsExactly("Java", "Kotlin");

 

2.5 람다식에 대한 지역변수 구문

Java 11부터 지역변수 구문을 람다식에 사용할 수 있다.

이 기능을 사용하여 타입 어노테이션을 정의하는 것과 같이 로컬 변수에 수정자를 적용할 수 있다

List<String> sampleList = Arrays.asList("Java", "Kotlin");
String resultString = sampleList.stream()
  .map((@Nonnull var x) -> x.toUpperCase())
  .collect(Collectors.joining(", "));
assertThat(resultString).isEqualTo("JAVA, KOTLIN");

 

2.6 HTTP Client

Java 9에서 소개되었던  java.net.http 패키지의 HttpClient가 Java 11에서 표준 기능이 되었다.

새로운 HTTP API는 전반적인 성능 향상과 HTTP/1.1, HTTP/2에 대한 지원을 제공한다.

HttpClient httpClient = HttpClient.newBuilder()
  .version(HttpClient.Version.HTTP_2)
  .connectTimeout(Duration.ofSeconds(20))
  .build();
HttpRequest httpRequest = HttpRequest.newBuilder()
  .GET()
  .uri(URI.create("http://localhost:" + port))
  .build();
HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
assertThat(httpResponse.body()).isEqualTo("Hello from the server!");

 

2.7 Nested class 에 대한 제어

다음과 같이 Nested class에 대한 제어를 제공한다.

assertThat(MainClass.class.isNestmateOf(MainClass.NestedClass.class)).isTrue();
assertThat(MainClass.NestedClass.class.getNestHost()).isEqualTo(MainClass.class);
Set<String> nestedMembers = Arrays.stream(MainClass.NestedClass.class.getNestMembers())
  .map(Class::getName)
  .collect(Collectors.toSet());
assertThat(nestedMembers).contains(MainClass.class.getName(), MainClass.NestedClass.class.getName());

 

2.8 Java 파일 실행하기

더이상 명시적으로 javac 명령어를 통해 Java 파일을 컴파일할 필요가 없다.

$ java HelloWorld.java
Hello Java 11!

 

 

※ 참조

https://www.baeldung.com/java-11-new-features

반응형
반응형

1. 불변 컬렉션

 자바 10에서는 불변 컬렉션(unmodifiable collections)와 관련한 몇 가지 변경 사항들이 있다.

 

1.1 copyOf()

 java.util.List, java.util.Map, java.util.Set 각각 copyOf() 라는 새로운 static 메서드가 생겼다. 이는 각 컬렉션의 복제된 불변 컬렉션을 반환한다.

@Test(expected = UnsupportedOperationException.class)
public void whenModifyCopyOfList_thenThrowsException() {
    List<Integer> copyList = List.copyOf(someIntList);
    copyList.add(4);
}

 

1.2 toUnmodifiable*()

 java.util.stream.Collectors는 Stream을 불변 컬렉션으로 collect하기 위한 추가적인 메서드를 List, Map, Set 별로 각각 제공한다.

@Test(expected = UnsupportedOperationException.class)
public void whenModifyToUnmodifiableList_thenThrowsException() {
    List<Integer> evenList = someIntList.stream()
      .filter(i -> i % 2 == 0)
      .collect(Collectors.toUnmodifiableList());
    evenList.add(4);
}

 위의 코드에서처럼 불변 컬렉션에 대해 변경을 시도하면 java.lang.UnsupportedOperationExceptionruntime이 발생할 것이다.

 

2. Optional*.orElseThrow()

 java.util.Optional, java.util.OptionalDouble, java.util.OptionalIntand java.util.OptionalLong 각각 orElseThrow()라는 새로운 메서드가 생겼다(기존에는 Supplier타입의 매개변수를 가진 단항함수만 존재했다). Optional 객체 내에 어떠한 값도 없을 경우, NoSuchElementException을 발생시킨다.

@Test
public void whenListContainsInteger_OrElseThrowReturnsInteger() {
    Integer firstEven = someIntList.stream()
      .filter(i -> i % 2 == 0)
      .findFirst()
      .orElseThrow();
    is(firstEven).equals(Integer.valueOf(2));
}

 이 메서드는 기존의 get() 메서드와 완전히 동일하며, 더 선호되는 방식이다.

 

3. 컨테이너 인식

 JVM은 이제 도커 컨테이너에서 실행되는 것을 인식하고 운영 체제 자체를 쿼리하는 대신 컨테이너별 구성을 추출한다. 이는 컨테이너에 할당된 CPU의 수 및 총 메모리와 같은 데이터에 적용된다. 그러나 이 기능은 Linux 기반 플랫폼에서만 사용할 수 있다. 이 기능은 기본적으로 활성화되어 있으며 JVM 옵션을 사용하여 명령줄에서 사용하지 않도록 설정할 수 있다. 

-XX:-UseContainerSupport

 

 또한 이 변경 사항은 JVM이 사용할 CPU 수를 지정하는 기능을 제공하는 JVM 옵션을 추가한다.

-XX:ActiveProcessorCount=count

 또한 도커 컨테이너 사용자가 Java 힙에 사용될 시스템 메모리의 양을 보다 세밀하게 제어할 수 있도록 세 가지 새로운 JVM 옵션이 추가되었다.

-XX:InitialRAMPercentage
-XX:MaxRAMPercentage
-XX:MinRAMPercentage

 

4. 사용 안 함 및 제거(Deprecations and Removals)

4.1 커멘드 라인 옵션, 툴

 native 메서드를 구현하기 위해 사용되는 C 헤더와 소스 파일을 생성하기 위해 사용되었던 'javah' 기능이 제거되었다. 대신 'javac -h' 를 사용할 수 있다.

 policytool은 정책 파일 생성 및 관리를 위한 UI 기반 도구인데 제거되었다. 사용자는 간단한 텍스트 편집기를 사용하여 이 작업을 수행할 수 있다.

 Java -Xprofoption이 제거되었다. 이 옵션은 실행 중인 프로그램을 프로파일링하고 프로파일링 데이터를 표준 출력으로 전송하는 데 사용되었다. 사용자는 이제 대신 jmap을 사용해야 한다.

 

4.2 APIs

 Deprecated된 java.security.acl 패키지는 @Deprecated(forRemoval = true)로 표시되었으며, 이는 이후 자바 버전에서 제거될 수 있다. 이것은 java.security.Policy 와 관련된 클래스로 대체되었다.

 비슷하게 java.security.{Certificate,Identity,IdentityScope,Signer} 클래스들도 forRemoval = true로 표시되었다.

 

5. 시간 기반 릴리즈 버전 관리

 Oracle은 Java 10을 시작으로 시간 기반 Java 릴리즈로 전환했다. 여기에는 다음과 같은 뜻이 있다.

 

1) 새로운 Java 릴리즈는 6개월마다 제공된다. 2018년 3월 릴리즈는 JDK 10이라면, 9월 릴리즈는 JDK 11가 되는 식이다. 이러한 방식을 기능 릴리즈라고 하며, 하나 또는 두 개의 중요한 기능이 추가되어야 한다. 

2) 기능 릴리즈는 다음 릴리즈가 나오는 6개월 동안만 지원된다.

3) 장기 지원 릴리즈(Long Term Support)는 LTS라고 표시될 것이다. LTS에 대한 지원 기간은 3년이고 Java 11이 LTS 버전이다.

 

 'java -version' 명령어는 이제 GA Date(General Availability Date)를 표시해줄 것이다. 이는 사용자의 JDK가 얼마나 오래되었는지를 쉽게 확인하는 것을 가능하게 해줄 것이다.

$ java -version
openjdk version "10" 2018-03-20
OpenJDK Runtime Environment 18.3 (build 10+46)
OpenJDK 64-Bit Server VM 18.3 (build 10+46, mixed mode)

 

※ 참조

https://www.baeldung.com/java-10-overview

반응형

+ Recent posts