SW/SW 서적

///Modern Java in Action / 한빛미디어

MG_ 2025. 2. 18. 08:21

 

1장. 자바 8, 9, 10, 11 : 무슨 일이 일어나고 있는가?

 

* Stream API

   - Stream 이란 한 번에 한 개씩 만들어지는 연속적인 데이터 항목들의 모임

   - 스트림을 이용하면 에러를 자주 일으키며 멀티코어 CPU 를 이용하는 것보다 비용이 훨씬 비싼 키워드 sychronized 를 사용하지 않아도 된다.

   - external iteration : for-each 와 같은 루프를 이용해 각 요소를 반복하면서 작업을 수행

   - internal iteration : Stream API 에서는 라이브러리 내부에서 모든 데이터가 처리됨

 

* pure/side-effect-free/stateless 함수

   - 공유된 가변 데이터에 접근하지 않아서 다른 코드와 동시에 실행하더라도 안전하게 실행할 수 있는 함수

 

* interface 의 default 메소드

   - 

 

* 자바의 함수

   - 메소드 개념에 더불어 수학적인 함수처럼 사용되며 부작용을 일으키지 않는 함수를 의미

 

 

2장. 동작 파라미터화 코드전달하기

 

* Behavior Parameterization (동작 파라미터화)

   - 실행 동작 즉, 메소드를 가진 객체를 파라미터로 전달하는 것을 의미

 

3장. 람다 표현식

 

* 람다

   - 메소드로 전달할 수있는 익명 함수를 단순화한 것

   - 메소드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다.

   - Parameter List, 화살표, Body로 구성

   - Expression-style : (parameters) -> expression

   - Block-style : (parameters) -> { statements; }

   - 함수형 인터페이스 문맥에서 사용할 수 있다

 

* 함수형 인터페이스

   - 하나의 추상 메소드를 지정하는 인터페이스

   - @FunctionalInterface 를 붙이면 지정 가능하다

 

* Function Descriptor

   - 람다 표현식의 시그니처를 서술하는 메소드

 

* Predicate

   - Generic 타입 T 객체를 받아서 true 나 false 를 반환하는 함수

   - @FunctionalInterface

     public interface Predicate<T> {

               boolean test(T t);

     }

   - @FunctionalInterface

     public interface BiPredicate<T, U> {

               boolean test(T t, U u);

     }

 

* Consumer

   - Generic 타입 T 객체를 받아서 void 를 반환하는 함수

   - @FunctionalInterface

     public interface Consumer<T> {

               void accept(T t);

     }

   - @FunctionalInterface

     public interface BiConsumer<T, U> {

               void accept(T t, U u);

     }

 

* Function

   - Generic 타입 T 객체를 받아서 Generic 타입 R 객체를 반환하는 함수

   - @FunctionalInterface

     public interface Function<T, R> {

               R apply(T t);

     }

   - @FunctionalInterface

     public interface BiFunction<T, U, R> {

               R apply(T t, U u);

     }

 

* Supplier

   - 객체를 전달 받지 않고 Generic 타입 T 객체를 반환하는 함수

   - @FunctionalInterface

     public interface Supplier<T> {

               T get();

     }

 

* UnaryOperator

   - Generic 타입 T 객체를 받아서 Generic 타입 T 객체를 반환하는 단항 연산자 함수

   - @FunctionalInterface

     public interface UnaryOperator<T> {

               T apply(T t);

     }

 

* BinaryOperator

   - Generic 타입 T 객체 2개를 받아서 Generic 타입 T 객체를 반환하는 이항 연산자 함수

   - @FunctionalInterface

     public interface BinaryOperator<T> {

               T apply(T t1, T t2);

     }

 

* 기본형 특화 함수형 인터페이스

   - Generic 내부 구현상 기본형 타입은 사용이 불가하기에 Integer, Long 등의 Wrapper 클래스를 이용하면 AutoBoxing 이 동작한다. 이러한 Cost 를 줄이기 위해 기본형 특화 함수형 인터페이스를 제공한다

   - IntPredicate, LongPredicate, DoublePredicate, ObjIntConstumer<T>, ToLongBiFunction<T, U> 등

 

* 형식 검사

   - 람다가 사용되는 Context 를 이용해서 람다의 Type (즉, Target Type) 을 추론하는 것 

   - 입력 파라미터와 출력 타입을 추론하여 함수형인터페이스를 추론

   - 다이아몬드 연산자 (<>)도 Context 를 사용해 추론한다

 

* Free Variable (자유 변수)

   - Parameter 로 넘겨진 변수가 아닌 외부 변수

 

* Capturing Lambda (람다 캡쳐링)

   - Body 에서 인스턴스 변수와 정적 변수만 자유롭게 캡처할 수 있다

   - 기본형 타입의 경우 final 로 선언되어 있어야 한다

   - 이러한, 지역변수 제약이 있는 것은 인스턴스 변수는 Heap 에 생성되는 반면에 지역변수는 Stack 에 위치하기 때문

 

* method reference (::)

  - 메소드를 가진 객체를 값으로 전달할 때 사용

  - 정적 메소드 참조

     (args) -> ClassName.staticMethod(args)

     ClassName::staticMethod

  - 다양한 형식의 인스턴스 메서드 참조

     (arg0, rest) -> arg0.instanceMethod(rest)

     ClassName::instanceMethod

  - 기존 객체의 인스턴스 메서드 참조

     (args) -> expr.instanceMethod(args)

     expr::instanceMethod

 

* 생성자 참조

   - new 키워드를 이용해서 생성자 참조를 만들 수 있다

   - Supplier<ClassName> supplier = ClassName::new;

 

 

3.7부터 보기