본문 바로가기

STUDY/기타

Java 8 ~ 11 버젼별 특징

그날 기분에 따라 정해지는 Java 버젼

 

 

Java8~11은 알고있어야겠다...

 


 

1. Java 1.8

 

2014년 3월 발표. 일반 지원은 2019년 1월에 종료되었고, 연장 지원은 2030년 12월에 종료될 예정이다.

 

 

1) Interface static And default method 

 

본래 Interface는 함수의 구현체 즉 body를 가질 수 없었다. 하지만 Java 1.8 부터는 인터페이스에 body를 가지는 static method와 default method가 추가되었다. 

 

// JavaInterface.java
public interface JavaInterface {
	static public String interfaceStaticMethod() {
		return "interfaceStaticMethod";
	}
}

// main 영역
public static void main(String[] args) {
	System.out.println(JavaInterface.interfaceStaticMethod());
	System.out.println(JavaInplementClass.interfaceStaticMethod()); // 에러발생
}

인터페이스의 static method는 클래스의 그것처럼, 객체 없이 호출될 수 있다. 하지만 인터페이스를 구현한 클래스에서는 호출 할 수 없으니 주의해야한다.

 

// JavaInterface.java
public interface JavaInterface {
	default public String defaultInterfaceMethod() {
		return "defaultInterfaceMethod";
	}
}

// main 영역
public static void main(String[] args) {
	JavaInterface javaInterface = new JavaInplementClass();
	System.out.println(javaInterface.defaultInterfaceMethod());
}

인터페이스의 default method는 해당 인터페이스의 구현 클래스에서 메소드 오버라이딩을 하지 않으면 호출되는 기본 구현체라고 할 수 있다.

 

 

2) Method References for lambda

 

이제 lambda 식이 들어가야 하는 곳에, 클래스의 메소드를 더욱 쉽게 참조 할 수 있게 되었다.

List<Integer> intList = new ArrayList<Integer>();
intList.add(0);
intList.add(1);
intList.add(2);

// 클래스의 static 메소드
List<List<Integer>> resultList = intList.stream().map(Arrays::asList).collect(Collectors.toList());
// 인스턴스의 메소드
List<Integer> resultList = intList.stream().map(intList::get).collect(Collectors.toList());
// 클래스의 생성자
List<Double> resultList = intList.stream().map(Double::new).collect(Collectors.toList());

System.out.println(intList);
System.out.println(resultList);

 

 

3) Optional

 

이전까지는 변수의 null 여부를 검사하고 대응하기위해, 개발자들은 많을 노력을 했어야 했다. Java 1.8 부터는 Optional이라는 구조체를 제공해서, 이전보다 간편하게 NPE(Null Pointer Exception) 이슈에 대응할 수 있다.

 

// Optional 구조체의 생성
Optional<String> optionalStr = Optional.empty();
Optional<String> optionalStr = Optional.of("str");
Optional<String> optionalStr = Optional.ofNullable("str");

// null 일 경우
System.out.println(optionalStr.orElse("empty str"));

// Optional 이전까지의 null 대응
String value = null;
String result = "";
try {
	result = value.toUpperCase();
} catch (NullPointerException exception) {
	throw new Exception();
}

// Optional 이후의 null 대응
String value = null;
Optional<String> valueOpt = Optional.ofNullable(value);
String result = valueOpt.orElseThrow(Exception::new).toUpperCase();

 

 

참조: https://www.baeldung.com/java-8-new-features


 

2. Java 9

 

자바 9은 2017년 9월에 발표되었고, 일반지원은 2018년 3월에 종료되었다.

 

1) Modular System – Jigsaw Project

 

이전까지 자바에서는 name space를 사용한 패키지와 gradle, maven을 사용하여 패키지와 라이브러리를 관리하였다. 하지만 기존의 방법들에는 문제가 있었다. 서로 다른 패키지간의 캡슐화가 지원되지 않았다.

 

> com.nankisu
  > com.nankisu.service
    > NankisuService.java
  > com.nankisu.util
    > NankisuUtil.java

위와 같은 구조의 라이브러리를 만들어서 배포했다고 생각해보자. NankisuService.java는 다른 사람들이 쓰도록 기능을 구현 한것이고, NankisuUtil.java는 패키지 안에서만 사용하기위해 구현했다. 하지만 "com.nankisu"를 import한 개발자는 NankisuService.java 뿐만 아니라 NankisuUtil.java에 public으로 구현된 기능들까지 접근 및 사용이 가능하다.

 

 

// module-info.java
module com.nankisu {
    requires com.baeldung.java9.modules.engines;
    exports com.nankisu.service;
}

자바 9에서 추가된 모듈 시스템에서는 위와 같이 module-info.java 파일에서 위와같이 관련 설정을 할 수 있다. 위 내용은 "con.nankisu"를 import하고 정상 동작을 하기 위해서는 "com.baeldung.java9.modules.engines" 모듈이 필요하고, "com.nankisu"에서 "com.nankisu.service" 패키지의 내용들만 사용하도록 하겠다는 의미이다.

 

 

2) A New HTTP Client

 

자바 1.8까지 사용하던 HttpURLConnection을 대체할 새로운 java.net.http 패키지가 추가되었다. 

 

HttpRequest request = HttpRequest.newBuilder()
  .uri(new URI("https://postman-echo.com/get"))
  .GET()
  .build();

HttpResponse<String> response = HttpClient.newHttpClient()
  .send(request, HttpResponse.BodyHandler.asString());

 

 

3) Process API

 

자바 9에서는 프로세스를 관리하는 기능이 더 강화되었다.

 

ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();
 
Optional<String[]> args = procInfo.arguments();
Optional<String> cmd =  procInfo.commandLine();
Optional<Instant> startTime = procInfo.startInstant();
Optional<Duration> cpuUsage = procInfo.totalCpuDuration();

 

childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
    assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});

 

 

4) Small Language Modifications

 

// Try-With-Resources
MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
    // do some stuff with mac
}
 
try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
   // do some stuff with finalCloseable
} catch (Exception ex) { }

 

 

// Diamond Operator Extension
FooClass<Integer> fc = new FooClass<>(1) { // anonymous inner class
};
 
FooClass<? extends Integer> fc0 = new FooClass<>(1) { 
    // anonymous inner class
};
 
FooClass<?> fc1 = new FooClass<>(1) { // anonymous inner class
};

 

 

// Interface Private Method
interface InterfaceWithPrivateMethods {
    
    private static String staticPrivate() {
        return "static private";
    }
    
    private String instancePrivate() {
        return "instance private";
    }
    
    default void check() {
        String result = staticPrivate();
        InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
            // anonymous class
        };
        result = pvt.instancePrivate();
    }
}}

 

 

5) JShell Command Line Tool

 

이전까지 자바 코드를 실행해보기 위해서는 main 메소드가 있는 클래스를 만들었어야 했다. JShell은 자바 코드를 한줄 한줄 실행해볼 수 있는 대화형 도구이다. 이제 마치 인터프리터 언어처럼 간단한 코드를 실행하고 테스트할 수 있게되었다.

 

jdk-9\bin>jshell.exe
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"

 

참조: https://www.baeldung.com/new-java-9


3. Java 10

 

자바 버전 10은 2018년 3월 20일에 발표되었다.

 

 

1) 지역 변수 추론 - var

 

이전까지는 변수를 선언할 때 그 타입을 명시해 줬어야 했다. 하지만 자바 10 부터는 

  • 지역 변수이고
  • 변수선언과 동시에 초기화 해주는 값이 있다면

특정한 타입 키워드 대신 var만 써주어도 컴파일러가 알아서, 타입을 추론해준다.

// String str = "hello"; 기존의 변수 선언
var str = "hello";
System.out.println(str.getClass().getTypeName()); // java.lang.String

 

 

2) Unmodifiable Collections - 수정할 수 없는 집합체

 

자바 10에서는 수정할 수 없는 집합체(map, list, set)에 관한 기능이 추가되었다.

 

List<Integer> numbers = new ArrayList<Integer>();

// copyOf()
List<Integer> copyedNumbers1 = List.copyOf(numbers);
copyedNumbers1.add(1); // throw java.lang.UnsupportedOperationException

// toUnmodifiable
List<Integer> copyedNumbers2 = numbers.stream().collect(Collectors.toUnmodifiableList());
copyedNumbers2.add(1); // throw java.lang.UnsupportedOperationException

 

 

3) Container Awareness - 컨테이너 인식

 

이제 JVM은 Docker 컨테이너 안에서 동작하는 것을 인식할 수 있습니다. 그리고 이에따라 컨테이너에 할당된 자원 역시 인식합니다.

 

 

4) Root Certificates - 기본 인증서

 

자바 10 이전까지는, Open-JDK에서 기본 인증서의 부재로 TLS등 관련 기능이 동작하지 않았다.(따로 인증서를 넣어주지 않았다면). 하지만 이제부터는 Oracle이 Open-JDK에 기본 인증서를 제공하기로 했다.

 

 

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


4. Java 11

 

자바 11은 2018년 11월에 발표 되었고, 자바 8 이후 첫 LTS(장기 지원) 버젼이다.

 

1) 새로운 기능들

새로운 String 기능들이 추가되었다. 

// repeat
String laWord = "La ";
String landWord = "Land";
System.out.println(laWord.repeat(2) + landWord);

// strip
String helloWorldWithWhiteSpace = "\n    \t Hello World    \n \u2005";
System.out.println(helloWorldWithWhiteSpace);
System.out.println(helloWorldWithWhiteSpace.strip());
System.out.println(helloWorldWithWhiteSpace.trim());

// isBlank
String whiteSpace = "\n\t";
System.out.println(whiteSpace.isBlank());
System.out.println(whiteSpace.isEmpty());

// lines
String multilineString = "Baeldung helps \n \n developers \n explore Java.";
List<String> nonBlankLineList = multilineString.lines().filter(line -> !line.isBlank()).map(String::strip).collect(Collectors.toList());
System.out.println(nonBlankLineList);

 

이제 파일에서 문자열을 더욱 쉽게 일고 쓸 수 있다.

Path filePath = Files.writeString(Files.createTempFile("test_", ".txt"), "Sample text");
String fileContent = Files.readString(filePath);
System.out.println(filePath.toFile().getAbsolutePath());
System.out.println(fileContent);

 

자바의 Collection에 기본기능으로 toArray가 추가되었다.

List<String> names = new ArrayList<String>();
String[] names_array = names.toArray(String[]::new);

 

Predicate에 not이 추가되었다. 기존의 !를 붙이던 방식대신 사용할 수 있다.

String multilineString = "Baeldung helps \n \n developers \n explore Java.";
List<String> nonBlankLineList = multilineString.lines()
  .filter(Predicate.not(String::isBlank))  // filter(line -> !line.isBlank()) 대신 사용
  .map(String::strip)
  .collect(Collectors.toList());

 

이제 lambda 식에서도 local variable syntax (var 키워드)를 사용할 수 있다.

List<String> sampleList = Arrays.asList("Java", "Kotlin");
String resultString = sampleList.stream()
  .map((var x) -> x.toUpperCase())
  .collect(Collectors.joining(", "));
System.out.println(resultString);

 

Java 9에서 소개되었던 HttpClient가 새로운 표준이 되었고, 더욱 기능이 강력해졌다.

HttpClient httpClient = HttpClient.newBuilder()
  .version(HttpClient.Version.HTTP_2)
  .connectTimeout(Duration.ofSeconds(20))
  .build();
HttpRequest httpRequest = HttpRequest.newBuilder()
  .GET()
  .uri(URI.create("http://localhost:8080"))
  .build();
HttpResponse<T> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());

 

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

728x90