컴파일 시에 타입을 입력받아서 사용하는 기능이다.
가장 흔하게 접할 수 있는경우는 Collection 클래스들이 있다
List<Integer> list = new ArrayList<>();
<> 를 사용하여 타입을 입력받는 것을 확인할 수 있다.
다양한 타입을 대상으로한 기능을 개발할 때 컴파일 단계에서 오류를 확인할 수 있다는 장점이 있다.
Tip: 타입 파라미터 종류
- T : reference Type
- E : Element
- K : Key
- V : Value
…
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable { ... }
객체 선언시에 타입을 입력받고, <> 이하의 {} 안에있는 모든 키워드에 해당하는 타입이 사용된다
extends 와 super 키워드를 이용하여 입력되는 타입을 제한하는 것이 가능하다
public class MyClass<T extends Number>{} // Number를 상속하는 클래스들만 객체 생성 시 설정가능
public class MyClass2<T super Number>{} // Number가 상속하고있는 클래스들만 설정가능
따로 타입을 제한하지 않으면 최상위 클래스를 의미하는 Object를 상속하는 타입으로 설정된다
만약 어떤 타입이 와도 상관없다면 ? 키워드를 사용하는 것이 좋다.
자바 8에서 추가된 기능으로, 함수형 인터페이스 표현하는데 사용되는 식이다.
함수형 인터페이스란, 하나의 추상메서드를 가진 인터페이스를 의미한다
public interface RunSomething{ void doIt(); }
함수형 인터페이스의 경우, 객체 생성시 아래와 같은 방식으로 익명 클래스를 이용할 수 있다
RunSomething rs = new RunSomething(){
@Ovverride
public void doIt(){ ... }
}
이러한 익명클래스를 통한 표현식을 좀 더 간결하게 표현하는 방식이 람다식이다
유의할 점은 익명클래스 != 람다식 이다
RunSomething rs = () -> { ... }
유의할 사항으로, 람다는 매개변수, 리턴값, 인스턴스화가 가능한 일급 함수라는 점이있다
또한, 람다식은 생성된 메서드를 벗어나는 것이 가능하기 때문에 지역변수를 참조할 때 복사해서 사용하는 특징이 있다
그렇기 때문에 해당 변수는 기존 값과의 동기화를 위해서 final 처럼 동작해야한다 ( Variable Capture )
추가적으로 익명클래스와 다르게 호출한 메서드와 동일한 scope를 가지기때문에 같은 이름의 매개변수명을 사용할 수 없다 ( Shadowing )
람다식(feat. 익명 구현 클래스 vs 람다식)
이와 관련하여 참고하기 좋은 블로그를 하나 남긴다
바이트코드까지 확인하여 직접 익명클래스와 람다식을 비교하는 포스팅이다