Java

[Java] Generic이란? 자세한 설명 (+ 동적 파라미터화, 함수형 인터페이스)

15호의 개발자 2022. 2. 13. 16:21
반응형

[Java] Generic이란? (동적 파라미터화, 함수형 인터페이스)

 

 

알아 둬야 할 것..

  1. Generic은 별 거 아니다!
  2. 동적 파라미터화 개념 이해하기
  3. 메서드를 인수로 전달하면서 람다식 사용하기
  4. 함수형 인터페이스 이해하기

 


 

Generic (제네릭)

지네릭에 대한 기본 개념은 아래의 두 링크를 통해 확인하고, 여기서는 좀 더 실용적인 면을 알아보겠다.

 

↓ 지네릭스에 대한 간단한 설명 ↓

 

[Java] 지네릭스(Generics)에 대한 간단한 설명

지네릭스(Generics)란? 지네릭스란 컴파일시 타입을 체크해 주는 기능이다. (JDK 1.5 이상부터 가능) ArrayList coffeeList = new ArrayList (); coffeeList.add(new Coffee()); // 컴파일 성공 coffeeList.add(ne..

unit-15.tistory.com

 

↓ 지네릭 프로그래밍 ↓

 

[Java] Generics란? 지네릭 프로그래밍(지네릭스)

[Java] Generics란? (지네릭스, 제네릭스) 지네릭스(Generics)란 컴파일시 타입을 체크해 주는 기능이다. (JDK 1.5 이상부터 지원된다.) 지네릭스 도입 전에는 형변환 에러(ClassCastException)가 일어날 때, 컴

unit-15.tistory.com

 


 

Generic 사용 방법

우선 generic의 사전적인 의미부터 알아보자.

generic [형용사]
1. 포괄적인, 총칭[통칭]의
2. 회사 이름이 붙지 않은, 일반 명칭으로 판매되는

사전적인 뜻 그대로, 지네릭은 타입을 명시할 때 통칭하는 타입으로 지정해두는 것이다.

 

 

제네릭 타입이란 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.

 

 

멀티 타입 파라미터제네릭 타입 선언 시 각각의 타입 파라미터를 콤마(,)로 구분하는 것이다. 별 거 없다. 원래 <T>라고 적을 것을, 멀티 타입에서는 <T, R>이나 <T, R, M> 등으로 적으면 된다.

 

 

다이아몬드 연산자 <>를 사용하면 컴파일러가 자동으로 타입을 추론해준다. 제네릭 사용 시 타입을 항상 명시해줬어야 하는데 다이아몬드 연산자가 도입된 이후에는 자동 타입 추론이 지원되어서 코드를 더욱 쉽게 읽을 수 있게 되었다.

참고로, 제네릭은 Java 5(jdk 1.5)부터, 다이아몬드 연산자는 Java 7(jdk 1.7)부터 도입되었다.

 

 

제네릭 메소드메소드의 선언 부에 적은 제네릭으로 리턴 타입과 파라미터의 타입이 정해지는 메소드이다. 아래와 같이 작성한다.

<T, R> R myMethod(T t)
<T, R>: generic type
R: return type
T: parameter type

 

 

제한된 타입 파라미터제네릭 타입의 상한을 제한할 때 사용한다. 최상위 타입과 그 자손들만 타입으로 사용할 수 있다. 상위 타입은 클래스뿐만 아니라 인터페이스도 가능하다.

<T extends 최상위타입>

 

 

와일드카드 타입 <?>은 제네릭 타입을 구현해서 사용하는데 그 타입이 어떤 타입인지 확실치 않을 때 사용한다.

  • <?>: 제한 없음
  • <? extends ...>: 상위 클래스 제한
  • <? super ...>: 하위 클래스 제한

 

 

(cf)

<T>와 <?>를 언제 써야할지 헷갈리다면 아래를 참고하면 된다.

  • 클래스를 만들 때 무슨 타입일지 모르겠음
    → 지네릭 <T>
  • 지네릭을 사용할 때 무슨 타입일지 모르겠음
    → 와일드카드 <?>

 

 

(추가 팁)

타입 파라미터로 배열 생성하려면 new T[n]으로 하면 안 되고, 아래와 같이 작성해야 한다.

(T[]) (new Object[n])

 


 

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

동작 파라미터화(behavior parameterization)란 아직은 어떻게 실행할 것인지 결정되지 않은 코드 블록을 의미한다.

여기서 말하는 동작 파라미터자주 바뀔 수 있는 부분(즉, 파라미터)에 설정하는 것이라고 생각하면 된다.

 

동작 파라미터화로 코드를 전달하기 위해서 predicate를 활용할 수 있다. predicate는 참 또는 거짓(boolean)을 반환하는 함수이다. 즉, predicate를 담고 있는 일반적인 인터페이스를 만들어 놓고, 실제 구현할 때는 필요한 후속 조건을 덧붙여서 쓴다. 이를 구현할 때는 코드의 간결함을 위해 익명 클래스(인터페이스를 일회용으로 구현해서 쓰고 싶은 경우 사용)를 사용하기도 하며, 메서드를 파라미터로 사용할 수도 있다.

 

 


 

Lambda Expressions (람다 표현식)

 

↓ 람다 표현식 간단한 설명↓

 

[Java] 람다식 (Lambda Expression, 람다 표현식)

[Java] 람다식 (Lambda Expression, 람다 표현식) 람다식은 함수(메서드)를 간단한 식(expression)으로 표현하는 바법이다. 람다식은 익명 함수(anonymous function)와 비슷한데, 사실은 익명 객체이다. 익명..

unit-15.tistory.com

 

람다 표현식에 대한 간단한 설명은 위의 링크를 참고하길 바라며, 여기서는 제네릭 및 메서드 참조와 관련된 실용적인 내용에 대해 다룬다.

 

람다 표현식은 자바 8부터 도입되었다. 람다식은 런타임시 익명 구현 객체가 되며, 기본 형태는 아래와 같다.

 (매개변수) -> {실행코드}

실행코드에 return문만 있는 경우에는 return과 중괄호는 생략 가능하다.

 

메서드 시그니처메서드의 매개변수와 반환 값 형식을 의미한다. 시그니처의 제네릭 타입이 같은지 같지 않은지를 비교하며 사용한다. (ex. (A, A) -> B)

 

함수 디스크립터란 람다 표현식의 시그니처를 서술하는 메서드를 의미하며, 함수형 인터페이스의 시그니처를 의미한다고 생각하면 쉽다. 

 


 

Method References (메서드 참조)

메서드 참조는 깔끔한 코드의 핵심이다.

 

메서드 참조도 람다식처럼 인터페이스의 익명 구현 객체로 생성된다.

 

  • 정적 메서드 참조 방법: ‘클래스 :: 메서드’
  • 인스턴스 메서드 참조 방법: ‘참조변수 :: 메서드’
  • 생성자 참조 방법: ‘클래스 :: new’

 


 

Functional Interface (함수형 인터페이스)

함수형 인터페이스추상 메서드가 하나만 있는 인터페이스를 의미한다.

(ex. Runnable - run, Callable - call, ...)

 

표준 API 분류에 따른 Java에서 기본 제공하는 대표적인 함수형 인터페이스는 아래와 같다.

함수형 인터페이스 디스크립터 메소드
Consumer T -> void accept
Supplier () -> T get
Function<T, R> T -> R apply
Operator<T, T> T -> T apply
Predicate T -> boolean test

 

 

반응형