CHAP21 - Modern-Java-in-Action/Online-Study GitHub Wiki

이 장의 내용

  • 자바 8의 기능과 자바 8이 프로그래밍 형식에 가져올 변화
  • 새로운 자바 9 모듈 시스템
  • 6개월 주기의 점진적 자바 릴리스 생명주기
  • 첫 번째 점진적 릴리스 자바 10
  • 미래 자바 버전에 추가되리라 기대하는 기능

21.1 자바 8의 기능 리뷰

자바 8에서 큰 변화가 생긴 이유

  • 자바 8에 추가된 대부분 기능 -> 함수형 프로그래밍을 쉽게 적용할 수 있도록 도와줌
  • 큰 변화가 생긴 이유
    • 개별 CPU 코어 속도가 빨라지며 병렬 실행시 코드 실행 속도 향상 가능
    • 간결하게 데이터 컬렉션을 처리하기 위함(불변 객체, 불변 컬렉션)

21.1.1 동작 파라미터화(람다와 메서드 참조)

  • 함수형 프로그래밍에서 지원하는 메서드로 코드 블록을 전달하는 기법
// Apple에 Predicate의 test에 해당하는 isGreenApple, isHeavyApple 구현
public class Apple {
	public boolean isGreenApple() {
		return GREEN.equals(color);
	}
	public boolean isHeavyApple() {
		return weight > 150;
	}
}

// Predicate를 파라미터로 받는다
public List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> applePredicate) {
	List<Apple> result = new ArrayList<>();
	for(Apple apple : inventory) {
		if(applePredicate.test(apple)) {
			result.add(apple);
		}
	}

	return result;	
}

// stream의 filter를 이용하면 더 간결하게 표현 가능
public List<Apple> filterApplesForStream(List<Apple> inventory, Predicate<Apple> applePredicate) {
	return inventory.stream().filter(applePredicate::test).collect(Collectors.toList());
}

// 다른 결과를 가져올 수 있음
List<Apple> greenApples = filterApples(inventory, Apple::isGreenApple);
List<Apple> heavyApples = filterApples(inventory, Apple::isHeavyApple);

또는 람다 표현식(lambda expression)을 이용하여 표현

List<Apple> redApples = filterApples(inventory, (Apple apple) -> RED.equals(apple.getColor()));
List<Apple> heavyApples2 = filterApples(inventory, (Apple apple) -> apple.getWeight() > 150);

21.1.2 스트림

  • 스트림 API는 파이프라인이라는 게으른 형식의 연산을 사용
  • 큰 데이터 집합일수록 스트림의 데이터 처리 방식이 효율적이며, 메모리 캐시 등의 관점에서도 탐색 횟수를 최소화 하는 것이 중요함
  • parallel 메서드로 스트림을 병렬로 처리
/*
* 1. 통화별로 트랜잭션을 그룹화한 다음에 해당 통화로 일어난 모든 트랜잭션 합계를 계산하시오(Map<Currency, Integer>)
* 2. 트랜잭션을 비싼 트랜잭션과 저렴한 트랜잭션 두 그룹으로 분류하시오(Map<Boolean, List<Transaction>>)
*/

// Collection 버전
Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
for (Transaction transaction : transactions) {
	Currency currency = transaction.getCurrency();
	List<Transaction> transactionsForCurrency = transactionsByCurrencies.get(currency);
	if (transactionsForCurrency == null) {
		transactionsForCurrency = new ArrayList<>();
		transactionsByCurrencies.put(currency, transactionsForCurrency);
	}
	transactionsForCurrency.add(transaction);
}

// Stream(함수형 프로그래밍) 버전
Map<Currency, List<Transaction>> transactionsByCurrencies2 = transactions.stream().collect(groupingBy(Transaction::getCurrency));

21.1.3 CompletableFuture 클래스

  • 자바5의 Future 인터페이스 : 여러 작업이 동시에 실행될 수 있도록 다른 스레드나 코어로 작업을 할당 가능(멀티코어 활용)
  • Future와 관련된 공통 디자인 패턴을 함수형 프로그래밍으로 간결하게 표현할 수 있도록 thenCompose, thenCombine, allOf 등을 제공
    • 명령형에서 발생하는 불필요한 코드 감소효과

21.1.4 Optional 클래스

  • T 형식의 값을 반환하거나 Optional.empty(값이 없음)라는 정적 메서드를 반환할 수 있는 Optional<T> 클래스
  • 값이 없을 때 에러를 발생시킬 수 있는 null 대신 정해진 데이터 형식을 제공
// BEFORE
String name = null;
if(insurance != null){
	name = insurance.getName();
}

// AFTER
Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance::getName);

21.1.5 Flow API

  • 자바9의 리액티브 스트림, 리액티브 당김 기반 역압력 프로토폴 표준화
  • Flow API는 호환성을 높일 수 있도록 라이브러리가 구현할 수 있는 네 개의 인터페이스 Publisher, Subscriber, Subscription, Processor 포함

21.1.6 디폴트 메서드

  • 인터페이스 설계자가 메서드의 기본 구현을 제공 가능
  • 인터페이스 구현 클래스들이 새로 추가된 기능을 구현하지 않아도 됨
// 상속과 관련된 문제가 있음..
public interface A {
      default void hello {
            print A
      }
}

public interface B extends A {
      default void hello {
            print B
      }
}

public class C implements B, A {
      public static void main(String... args) {
            new C().hello();	// print B
      }
}

21.2 자바 9 모듈 시스템

  • 자바 9에서 추가된 내용
    • 스트림의 takeWhile, dropWhile 추가
    • CompletableFuture의 completeOnTimeout 추가
    • 모듈 시스템 - module-info.java 파일 추가
  • 다른 릴리스에 비해 과거 호환성을 해쳤다는 의견
    • 모듈화라는 장점을 얻기 위한 불가피한 희생
  • 자바 모듈 시스템이 제공하는 장점
    • 안정적 설정
    • 강한 캡슐화
    • 보안성 개선
    • 성능 개선
    • 확장성

21.3 자바 10 지역 변수형 추론

  • 자바7 : 변수가 메서드를 정의할 때 컨텍스트로 형식을 유추할 수 있는 상황에서는 생략 가능
Map<String, List<String>> myMap = new HashMap<String, List<String>>();
-> Map<String, List<String>> myMap = new HashMap<>();
  • 자바10 : 로컬변수 선언을 var를 이용하여 컴파일러에게 타입을 추론하게할 수 있도록 함
var list = new ArrayList<String>(); // infers ArrayList<String> 
var stream = list.stream(); // infers Stream<String> 
var numbers = List.of(1, 2, 3, 4, 5); 
for (var number : numbers) { 
	System.out.println(number); 
} 
for (var i = 0; i < numbers.size(); i++) { 
	System.out.println(numbers.get(i)); 
}

자바 11의 새로운 기능

  • String 클래스의 새로운 메서드
    • 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.");
  • Files 클래스에 readString, writeString 추가
Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo", ".txt"), "Sample text");
String fileContent = Files.readString(filePath);
assertThat(fileContent).isEqualTo("Sample text");
  • 컬랙션의 toArray() 메서드를 오버로딩하는 메서드 추가 -> 원하는 타입의 배열 선택 가능
List<String> sampleList = Arrays.asList("Java", "Kotlin");
String[] sampleArray = sampleList.toArray(String[]::new);
  • Predicate 인터페이스에 not 메서드 추가
  • 자바 컴파일없이 실행 가능
# before
$ javac HelloWorld.java
$ java HelloWorld 
Hello Java 8!

# after
$ java HelloWorld.java
Hello Java 11

마무리

지금까지 배움이라는 여행을 즐겼길 바란다.
그리고 앞으로 일어날 자바의 진화를 살펴보는 데 더 많은 관심이 생겼길 희망한다

⚠️ **GitHub.com Fallback** ⚠️