이중 콜론 연산자 (Double Colon Operator) 람다(Lamda)식과 함께 살펴보려고 한다.
- 람다식과 이중 콜론 연산자를 이용하면 간결하게 표현할 수 있는데, 예를 들어 comparator를 생성해보자
#1 lamda
Comparator c = (Computer c1, Computer c2) -> { c1.getAge().compareTo( c2.getAge() ) };
#2 lamda
Comparator c = (c1, c2) -> { c1.getAge().compareTo( c2.getAge() };
#3 ::
Comparator c = Comparator.comparing(Computer::getAge());
위에 두 람다식보다 이중콜론 연산자가 훨씩 읽기 쉽고 짧게 표현할 수 있다.
- 이전에는 java에서 아래와 같이 inner class를 이용해 구현해야 했다.
Comparartor<Computer> abstractInnerClass = new Comparator<Computer>(){
@Override
public int compareTo(Computer c1, Computer c2){
return c1.getAge().compareTo(c2.getAge());
}
}
- :: 사용법
사용법은 targetReference :: methodName 즉 타겟레퍼런스 :: 메소드명 = Computer::getAge;
(이름만으로 특정 메소드를 호출할 수 있도록 :: 연산자를 사용)
함수를 참조하고 있다는 것과 함수의 인자가 정확해야 한다는 것에 주목해야 한다.
#!
Computer::getAge;
#2
Function<Computer, Integer> getAge = Computer::getAge();
Integer ComputerAge = getAge.apply(c1);
[#2 코드] getAge는 Computer의 getAge()함수를 호출하는데, getAge에 c1을 적용하면
컴퓨터 c1의 getAge()메소드를 호출해 age를 반환한다. ?
- 이중콜론을 사용할 수있는 여러 방법들이 있다. (Method Reference)
1. 정적 메소드 static utility method
#ComputerUtils 의 repair 가 정적 메소드라고 가정하고
List inventory = Arrays.asList(
new Computer( 2015, "white", 35), new Computer(2009, "black", 65));
inventory.forEach(ComputerUtils::repair);
2. 기존 객체의 인스턴스 메소드 an Instance Method of an Existing Method
'기존 객체의 인스턴스의 메소드를 참조하는 흥미로운 예제' 를 보자
Computer c1 = new Computer(2015, "white");
Computer c2 = new Computer(2009, "black");
Computer c3 = new Computer(2014, "black");
Arrays.asList(c1, c2, c3).forEach(System.out::print);
java 에 이미 정의된 기존 객체의 인스턴스(System.out) 의 메소드(print) 를 호출하기도 한다.


3. 새로 생성한 객체의 인스턴스 메소드 an Instance Method of an Arbitrary Object of a Particular Type
Computer c1 = new Computer(2015, "white", 100);
Computer c2 = new MacbookPro(2009, "black", 100);
List inventory = Arrays.asList(c1, c2);
inventory.forEach(Computer::turnOnPc);
사용자가 정의한 Computer라는 클래스의 turnOnPc 메소드를 호출할 수도 있다.
특정 인스턴스가 아니라 유형 자체(Computer) 에서 turnOnPc 메소드를 참조하고 있다.
4행에서 인스턴스 메소드 turnOnPc 는 인벤토리의 모든 개체에 대해 호출된다.
그리고 이것은 자연스럽게 – c1의 경우 turnOnPc 메서드 가 Computer 인스턴스 에서 호출되고 c2의 경우 MacbookPro 인스턴스 에서 호출 됨을 의미 합니다.
4. 특정 개체의 슈퍼 메소드
Computer(super class)에 calculateValue라는 메소드가 있다고 가정하자.
public Double calculateValue(Double initialValue) {
return initialValue/1.50;
}
그리고 MacbookPro(sub class) 에서 calculateValue를 재정의 해보자.
@Override
public Double calculateValue(Double initialValue){
Function<Double, Double> function = super::calculateValue;
Double pcValue = function.apply(initialValue);
return pcValue + (initialValue/10) ;
}
MacbookPro 인스턴스에서 calculateValue 메소드를 호출하면, Computer(super class)의 calculateValue도 호출될 것이다.
타겟 메소드에 클래스이름이 아닌 super 도 올 수 있다는 것을 의미한다.
macbookPro.calculateValue(999.99);
- 구조 참조 Constructor Reference
1. 새로운 인스턴스 생성하기
객체를 인스턴스화 하는 생성자를 참조할 수도 있는데 매우 간단하다.
@FunctionalInterface
public interface InterfaceComputer{
/*public abstract*/ Computer create();
}
InterfaceComputer c = Computer::new;
Computer computer = c.create();
생성자에서 두개의 파라미터를 가지는 경우는 다음처럼 하면 된다.
BiFunction<Integer, String, Computer> c4Function = Computer::new;
Computer c4 = c4Function.apply(2013, "white");
생성자가 세개 이상의 파라미터를 가지는 경우는 새로운 Functional interface를 정의해줘야 한다.
@FunctionalInterface
interface TriFunction<A, B, C, R> {
R apply(A a, B b, C c);
default <V> TriFunction<A, B, C, V> andThen( Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (A a, B b, C c) -> after.apply(apply(a, b, c));
}
}
2. 배열 생성하기
5개의 Computer 객체의 배열을 만들 수도 있다.
Function <Integer, Computer[]> computerCreator = Computer[]::new;
Computer[] computerArray = computerCreator.apply(5);
아직 내가 잘 활용할 수 있을 지 모르겠지만, 이중콜론이 무엇인지 어떤 식으로 사용하는 지 알게 되었다. 특히 stream을 활용 할때 좋다고 하니 평소에 문자열이 다루기 까다롭다고 생각했던 입장에선 얼른 적용시켜봐야겠다는 생각이 든다.
참고로 funtional interface를 포함한 interface에 관한 설명도 올릴 예정이다.
참고
https://www.baeldung.com/java-8-double-colon-operator
http://wiki.sys4u.co.kr/pages/viewpage.action?pageId=7766725
http://wiki.sys4u.co.kr/pages/viewpage.action?pageId=7766725
페이지 … PLATEER OPEN WIKI Programming Tips JSDK 배너의 맨 끝으로 배너의 맨 처음으로 이중 콜론 연산자 메타 데이터의 끝으로 건너뛰기 수진 이님이 작성, 9월 20, 2017에 최종 변경 메타 데이터의 시작
wiki.sys4u.co.kr
'java' 카테고리의 다른 글
java 중복 없애주는 set, 객체는? (0) | 2022.05.11 |
---|---|
java optional stream() (0) | 2022.02.03 |
[String] replace, replaceAll과 정규식 (0) | 2021.11.17 |
제네릭 클래스 Generics, 제너릭 클래스 메서드, <T> (0) | 2021.09.13 |
댓글