Study/Java&Spring

알아 두면 좋은 Java 기능 정리

kdhoooon 2022. 4. 25. 10:06

 

함수형 인터페이스 

- 추상메서드가 하나만 있는 경우, 두개 이상은 불가능(다른형태의 메서드가 여러개 있는건 상관 없음 오로지 추상메서드만 한개 있어야함), @FuncionalInterface 로 선언하여 사용

 

 

Java8 에서 인터페이스 - static 메서드 정의 가능, default 메서드 정의 가능

 

 

함수형 인터페이스는 순수한 함수여야 한다.

  1. 항상 같은 값에는 같은 결과값을 리턴해야한다. (=멱등해야한다.),
  2. 외부에 있는 값을 변경하면 안된다. 

 

자바에서 제공하는 주요 함수형 인터페이스 종류

 

Function<T, R> 

  • T 타입을 받아서 R 타입을 리턴하는 힘수 인터페이스
  • 함수 조합용 메소드
  • andThen    -> A.andThen(B) B 실행 결과값을 가지고 A를 수행
  • compose    -> Acompose(B) A 실행 결과값을 가지고 B를 수행

BiFunction<T, U, R>

  • 두 개의 값(T, U)를 받아서 R 타입을 리턴하는 함수 인터페이스
  • R apply(T t, U u)

Consumer<T>

  • T 타입을 받아서 아무값도 리턴하지 않는 함수 인터페이스
  • Void Accept(T t)
  • 함수 조합용 메소드
  • andThen

Supplier<T>

  • T 타입의 값을 제공하는 함수 인터페이스
  • T get()

Predicate<T>

  • T 타입을 받아서 boolean을 리턴하는 함수 인터페이스
  • boolean test(T t)
  • 함수 조합용 메소드
  • And  ->  함수들의 결과를 and 연산하여 결과를 리턴함
  • Or  ->  함수들의 결과를 or 연산하여 결과를 리턴함
  • Negate  ->  결과를 not 연산하여 결과를 리턴함

UnaryOperator<T>

  • Function<T, R>의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수 인터페이스

BinaryOperator<T>

  • BiFunction<T, U, R>의 특수한 형태로, 동일한 타입의 입력값 두개를 받아 리턴하는 함수 인터페이스

 

 

람다 표현식

  • (인자리스트) -> {바디} 형태로 구현 할 수 있다.

 

인자리스트

  • 인자가 없을 경우 (), 한개일 경우(arg) 또는 arg, 여러개일 경우 (arg1, arg2, arg2, …)
  • 인자의 타입은 생략가능하다.

바디

  • 여러 줄인 경우에 {} 로 묶어서 사용한다.
  • 한 줄인 경우에는 {}를 생략해도 된다. return도 생략할 수 있다.

 

메소드 레퍼런스

  • Lambda 표현식을 좀 더 간결하게 표현하는 방식

인터페이스 기본 메서드(Default Methods)

  • 인터페이스에 메서드 선언이 아니라 구현체를 제공하는 방법
  • 해당 인터페이스를 구현한 클래스를 깨트리지 않고 새 기능을 추가 할 수 있다.
  • 기본 메서드는 구현체가 모르게 추가 된 기능인 만큼 리스크가 있다.(구현이 안 될 수 있다.)
  • 컴파일 에러는 아니지만 구현체에 따라 런타임 에러가 발생할 수 있다.
  • 반드시 문서화 하는 것이 중요하다(@implSpec 자바독 태그 사용)
  • Object가 제공하는 기능(equals, hasCode)는 기본 메서드로 제공 할 수 없다.
  • 구현체가 재정의 해서 사용해야 함
  • 여러개를 인터페이스를 다중상속을 통해 구현했을 때, 기본 메서드(Default Mehtods)가 충돌하는 경우 직접 재정의해서 사용해야 함(자바에서는 이를 커파일 에러로 구분해버리기 때문)
  • 수정할 수 있는 인터페이스에만 기본 메소드를 제공할 수 있다.

인터페이스 스태틱 메서드(Static Method)

  • 유틸리티나 헬터 메서드를 제공할 때 사용 함

위의 인터페이스로 인해 API개발의 변화가 일어남

 

Java8 이전의 방식(클래스 상속을 이용)

  • 인터페이스를 상속하는 추상클래스를 만들고, 이 추상클래스를 상속받는 클래스에서 인터페이스의 메서드를 각각 구현시켜서 사용
  • 단점 : 상속은 하나만 가능하기 때문에 한계가 있다

Java8에서 사용

  • 인터페이스를 구현하여 implements 해서 사용
  • 장점 : 상속이 강제되지 않는다(비 침투성), 코드가 간결해짐
  • Spring 에서는 상속을 강제하지 않는 방식을 선호함

 

Stream

  • 연속 된 자원을 병렬적으로 처리하는 방법
  • 하나의 컨베이어 벨트가 진행되며 상품이 만들어지는 방식과 유사
  • 스트림이 처리하는 데이터 소스를 변경하지 않는다
  • 스트림으로 처리하는 데이터는 오직 한번반 처리한다
  • 중개 오퍼레이션은 근본적으로 lazy 하다 -> 종료 오퍼레이션이 오기전까지 중개 오퍼레이션은 처리하지 않는다.
  • 손쉽게 병렬 처리를 할 수 있다.

 

중개 오퍼레이션

  • Stream을 리턴
  • Stateless / Stateful 오퍼레이션으로 더 상세하게 구분 할 수도 있다.( 대부분은 Stateless지만, distinct나 sorted 처럼 이전 이전 소스 데이터를 참조해야 하는 오퍼레이션은 Stateful 오퍼레이션이다.)
  • 종류 : filter, map, limit, skip, sorted, …

종료 오퍼레이션

  • Stream을 리턴 X
  • 종류 : collect, allMatch, count, forEach, min, max …

 

 

Optional

  • 오직 값 한개가 들어있을 수도 없을 수도 있는 컨테이너
  • NullPointException 예외가 발생하는 원인을 해결하기 위해서 주로 사용(null 체크를 해서 해결 해도 되지만 깜빡하는 경우가 많기 때문에)
  • 사용시 주의사항
  • 리턴 값으로 만 사용하길 권장 함
  • Optional을 리턴하는 메서드에서 null을 리턴하지 말자
  • 프리미티브 타입용 Optional이 따로 있다. Ex) OptionalInt, OptionalLong, … 
  • Collection, Map, Stream Array, Optional Optional 감싸면 안된다.