자바 버전

  • 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!");
    };

 

 

 

출처 

 

Guide to Java Versions and Features - DZone Java

In this guide. we will look at the differences between Java distributions and an overview of Java language features, including Java versions 8-13.

dzone.com

 

미리보는 java9 - 머루의개발블로그

오늘은 미리보는 java9의 새로운 기능들을 살펴보자. 물론 지금은 릴리즈전이라 바뀔 내용이 있을 수 있으니 너무 깊게는 살펴보지 말자. 조만간 java9가 릴리즈 될 예정이다. 원래 일정은 올해 초

wonwoo.ml