익명 함수와 람다를 문법, 성능 관점에서 비교해보려한다.
이외 제네릭, 공변, 반공변, 불공변도 정리하려한다.
우선 익명 함수부터 보겠다.
익명 함수
- 메서드가 1개인 인터페이스를 정식 함수 선언 없이 바로 함수 선언해 사용하는 문법
- 함수를 정식 선언하는 것 대비 메모리 측면에서 효율적(사용 후 메모리 할당 사라짐)
다음은 비교 대상인 람다이다.
람다
- 함수형 인터페이스의 인스턴스를 생성해 함수를 변수처럼 선언하는 것
- 익명 함수의 불필요한 코드를 줄이고, 가독성을 높이기 위함
- JAVA 8에서 추가됨
람다가 나온 이상 스트림이 빠질 수 없다.
다음은 스트림이다.
스트림
- 자바 8부터 추가된 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자
- Iterator와 비슷한 역할을 하지만, 람다식으로 요소 처리 코드를 제공해 좀 더 간결한 점과 내부 반복자를 사용하므로 병렬처리가 쉽다
익명 함수 vs 람다 문법 비교
익명 함수
- 인터페이스 내 선언되어있는 함수 전체를 구현해줘야함
람다
- () -> {}로 매개 변수 및 함수 선언부를 구현해버림
- 추상 클래스의 인스턴스를 만들 때 람다를 쓸 수 없다(익명클래스 사용해야함)
- 추상 메서드가 여러개인 인터페이스의 인스턴스도 불가능하다.
- 람다는 자신을 참조할 수 없다.(람다의 this는 바깥 인스턴스를 가리키고 익명클래스의 this는 자신을 가리킨다)
익명 클래스와 람다는 직렬화하는 일은 극히 삼가야 한다(구현별로 다를 수 있다)
코드의 간결성에 있어서 람다가 압도적임
for vs 람다 스트림 비교
- 일반적인 경우 for 성능이 더 좋다
하지만, Collection으로 구성할 경우 동등할 정도로 빨라질 수 있다
성능이 중요할 경우 기존 for로 돌려라
불공변
- 상속 관계에 상관없이, 자기 타입만 허용하는 것
- 제네릭과 연관시키면 특정 타입만 제네릭으로 선언해놓은 것
공변
- 자기 자신과 자식 객체를 허용하겠다는 의미
- 제네릭과 연관시키면 extends 키워드를 써 자기 자신과 상속받은 자식까지 허용하겠다는 것
반공변
- 공변의 반대로 자기 자신과 부모만 허용
- 자바 문법에선 불가능