자바 버전 별 정리
자바 버전
- Java Version은 6개월 마다 최신 버전이 있다.
- 자바 8이 많은 회사에서 채택하는 이유는 아래와 같다.
- Build Tool (Maven, Gradle 등) 이 자바 8 버전 이상에서 특정 라이브러리에 대해 버그를 가지고 있다. 특히, 이것은 자바 9 이상 부터는 Build Tool을 이용하여 Build하게 되면 "reflective aceess - warnings" 가 나오게 된다.
- reflective access - warning 에 대해서는 reflection 할 때 accessor 권한에 따라 public 인 경우에만 허용해줘서 warning 발생하게 된다.
- 자바8는 Oracle JDK 에 대해 라이선스를 고려할 필요가 없었지만 Oracle은 2019년 라이선스 체계를 변경하여 더이상 무료가 아닌것을 언급한적이 있다.
JRE 및 JDK 차이점
- JRE는 Java Runtime Environment 이고 JDK는 Java Development Kit 이다.
- 보통의 경우 Java 실행에만 관심이 있는 경우 JRE를 다운로드 한다. 개발을 진행하려면 JDK를 다운받는것이 일반적이다.
- 자바 8까지는 JRE + JDK 별도 다운로드를 제공하였지만, 자바9 에서부터는 항상 JDK 를 다운받도록 하였다.
자바 버전별 특징 8-13
자바8
- 자바 8 이전에서 Runnable 인스턴스를 구현한다고 하면 아래 처럼 익명의 이너 클래스를 생성할 것이다.
- Runnable runnable = new Runnable(){ @Override public void run(){ System.out.println("Hello world !"); } };
- 그런데 이것을 자바8의 lambda로 작성하면 아래 처럼 작성할 수 있다.
-
Runnable runnable = () -> System.out.println("Hello world two!");
- 자바8에서 collections 처리를 위한 Stream API를 활용해 functional-style을 적용할 수 있다. 아래 코드를 조회하기 위해서는 for-loop를 작성하여 리스트의 원소들을 확인하여 처리해줘야 하지만, stream을 쓰면 filter, map, sort 기능을 한번에 사용할 수 있다.
-
List<String> list = Arrays.asList("franz", "ferdinand", "fiel", "vom", "pferd");
-
list.stream() .filter(name -> name.startsWith("f")) .map(String::toUpperCase) .sorted() .forEach(System.out::println);
- 개발할 때 가장 많이 발생하는 예외는 NPE 이다. null을 검사하는 로직을 추가해야 하는데 null 검사를 해야하는 변수가 많은 경우 코드가 복잡해지고 로직이 상당히 번거로워진다.
- 자바8에서는 Optional<T> 클래스를 사용해 NPE를 방지한다. null이 올 수 있는 값을 감싸는 Wrapper클래스로 참조하더라도 NPE가 발생하지 않는다. Optional.ofNullable(..)를 사용한다.
- 이와 비교되는 개념으로 orElse, orElseGet이 존재한다.
- orElse : Optional 안에 null이든 아니든 항상 호출된다.
- orElseGet : Optional 안의 값이 null인 경우만 호출된다.
- 자바8에서는 Builder 를 Lambda로 구성할 수 있다. 예를 들어, new foo(a,b,c,d,e,f,...,z) 를 new builder().a(a).b(b)...build()로 보기 좋게 바꾼다. 여기서 실수, 오타의 여지를 줄여준다. 생성 parameter에 제약조건을 부여할 수 있다. (타입, 필수 여부 등)
-
public class PersonBuilder { public String salutation; public String firstName; public String middleName; public String lastName; public String suffix; public Address address; public boolean isFemale; public boolean isEmployed; public boolean isHomewOwner; public PersonBuilder with( Consumer<PersonBuilder> builderFunction) { builderFunction.accept(this); return this; } public Person createPerson() { return new Person(salutation, firstName, middleName, lastName, suffix, address, isFemale, isEmployed, isHomewOwner); } }
- 이후 builder()를 적용한 코드에서는 아래와 같이 쓸 수 있다.
-
Person person = new PersonBuilder() .with($ -> { $.salutation = "Mr."; $.firstName = "John"; $.lastName = "Doe"; $.isFemale = false; }) .with($ -> $.isHomewOwner = true) .with($ -> { $.address = new PersonBuilder.AddressBuilder() .with($_address -> { $_address.city = "Pune"; $_address.state = "MH"; $_address.pin = "411001"; }).createAddress(); }) .createPerson();
자바9
- Lists, Sets, Maps를 구성할 수 있는 Collections에 팩토리 메서드를 제공한다. 이러한 컬렉션들은 immutable 하기 때문에 변경할 수 없다. List.of()로 생성하고 add() 메서드를 호출하면 UnsupportedOperationException이 발생한다.
-
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");
- Stream도 takeWhile, dropWhile, iterate 메서드를 추가로 제공한다.
- takeWhile 메서드 형태는 아래와 같다.
-
default Stream<T> takeWhile(Predicate<? super T> predicate)
- takeWhile는 특정 엘리먼트까지 왔다면 멈추고 그 엘리먼트를 반환한다.
-
List<Integer> numbers = List.of(1, 3, 7, 8, 15, 4) .stream() .takeWhile(i -> i < 10) .collect(toList()); //[1, 3, 7, 8] List<Integer> numbers = List.of(1, 3, 7, 8, 15, 4) .stream() .filter(i -> i < 10) .collect(toList()); //[1, 3, 7, 8, 4]
- dropWhile 메서드 형태는 아래와 같다.
-
default Stream<T> dropWhile(Predicate<? super T> predicate)
- dropWhile는 takeWhile랑 다르게 반대로 조회한다.
-
List<Integer> numbers = List.of(1, 3, 7, 8, 15, 4) .stream() .dropWhile(i -> i < 10) .collect(toList()); //[15, 4]
- ofNullable 메서드 형태는 아래와 같다.
-
public static<T> Stream<T> ofNullable(T t)
- Java 8에서 Optional API를 이용해 Optional.ofNullable(value) 로 null인지 아닌지 확신할 수 없는 객체를 담고있는 Optional객체와 굉장히 유사하다. null에 safe한 메서드이고 아래와 같이 사용한다.
-
Stream.ofNullable(null)
- Optional에 stream(), or(), ifPresentOrElse() 메서드가 추가된다.
- Stream 타입 메소드는 아래와 같다.
-
public Stream<T> stream()
- Optional 타입을 만들어서 stream 형태로 만든다.
-
Optional<String> foo = Optional.ofNullable("foo"); Stream<String> stream = foo.stream();
- ifPresentOrElse(Consumer<? super T> action) 메서드 형태에서 확장되었다. ifPresent() 메서드는 값이 있을 경우만 동작하고 ifPresentOrElse() 메서드는 값이 없을 경우 동작하는 부분이 추가된다.
-
public void ifPresentOrElse(Consumer<? super T> action, Runnable emptyAction) Optional<String> foo = Optional.ofNullable("foo"); foo.ifPresentOrElse(f -> System.out.println(f), () -> System.out.println("bar")); // foo Optional<String> foo = Optional.ofNullable(null); foo.ifPresentOrElse(f -> System.out.println(f), () -> System.out.println("bar")); // bar
- ProcessHandle 인터페이스가 추가된다. Process 관련 정보를 가져올 수 있다.
-
ProcessHandle processHandle = ProcessHandle.current(); ProcessHandle.Info processInfo = processHandle.info(); long pid = processHandle.pid(); System.out.println(pid); System.out.println(processInfo.command().get()); System.out.println(processInfo.startInstant().isPresent()); System.out.println(processInfo.totalCpuDuration().isPresent());
- 자바8에서는 인터페이스에 구현을 할 수 있다.
-
interface SomeInterface { default void doSomething() { System.out.println("blabla"); } }
- 자바9 에서는 메서드에 private 접근제한을 둘 수 있다. protected나 default 접근제한은 사용할 수 없다.
-
interface SomeInterface { private void doSomething(){ System.out.println("blabla"); } }
- Reactive API가 Java9에 추가되었다. (잘 모르겠다. 시간이 되면 좀 더 공부하는것으로 ...)
- HTTP 클라이언트 기능이 추가되었다. Java에 내장 HTTP 지원은 다소 낮은 수준이었고 Apache HTTPClient 혹은 OkHttp 와 같은 타사 라이브러리를 사용해야 했다.
- 자바9 에서는 자바 자체적인 최신 클라이언트를 갖게 된다.
자바 10
- var keyword를 제공한다. 이러한 형식을 var - keyword 라고 한다.
-
// Pre-Java 10 String myName = "Marco"; // With Java 10 var myName = "Marco"
자바 11
- String & 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);
- 또, 소스 파일을 컴파일 하지 않고 실행시킬 수 있다.
-
ubuntu@DESKTOP-168M0IF:~$ java MyScript.java
자바 13
- fall-through/break 문제 없이 표현식에 람다 스타일 구문을 사용할 수 있다.
- 이전에 switch 문을 보면 아래와 같이 쓸 수 있다.
-
switch(status) { case SUBSCRIBER: // code block break; case FREE_TRIAL: // code block break; default: // code block }
- 자바13에서는 switch statement를 아래와 같이 lambda와 같이 쓸 수 있다.
-
boolean result = switch (status) { case SUBSCRIBER -> true; case FREE_TRIAL -> false; default -> throw new IllegalArgumentException("something is murky!"); };
출처