run이라는 메서드가 사라졌습니다. 해석을 하자면 run() 메서드에 전달할 인수가 없기에 동작할 코드를 " -> " 메서드를 사용하여 대 괄호 안에 전달합니다.
확실히 익명 함수를 사용했을 때보다는 람다식을 쓴 것이 상당히 이쁘기도 한 모습입니다.
람다식의 여러 가지 형태
람다식은 여러 가지 형식으로 구현할 수 있습니다.
(String a, String b)->{a +" + "+ b;}// 매게변수가 있는 기본구조(String a, String b)-> a +" + "+ b;// 대괄호를 생략할 때(int a1 + int a2)->{return a1 + a2;}// 리턴문을 사용할 때()->{return1+2;}// 매게 변수가 없을 때
이렇게 할 수 있습니다. 제가 많이 쓰는 형식은 두 번째 형식으로 매개변수가 실행될 때 함수가 실행되도록 하는 형식을 자주 씁니다.
대괄호를 사용하지 않는 경우는 실행 문장이 하나일 때 사용하지 않습니다. 그 외에는 대괄호가 꼭 필요합니다.
람다식, 하나의 추상메서드를 가진 클래스
람다식은 메서드를 새롭게 선언하는 것처럼 보일 수 있습니다. 하지만 자바는 엄청난 객체지향 언어이기에 항상 메서드를 클래스의 구성 멤버를 선언해야 합니다. 그렇기에 객체의 형식을 가져야 합니다. 말은 이렇지만 사용하는 모습을 보면 간단합니다.
(Interface) obj =(int q, int w)-> q + w;
사실상 간단합니다. 위에서 String을 쓴 것과는 조금 다릅니다. 인터페이스를 사용해야 하기 때문이죠.
interfaceinterMine{publicvoidadd(int a, int b);}
이러한 인터페이스가 있습니다. 이 인터페이스를 사용한 람다식을 보시죠.
interMine im =(int a, int b)-> a + b; im.add();
이렇게 사용을 하면 두 번째 줄에서 인터페이스에 있는 메서드를 호출하게 됩니다.
매개변수를 사용하지 않는 경우에는 이렇게 사용합니다.
interMine im =()->{~~~}
그냥 빈 괄호를 넣으면 사용이 가능해집니다. 매개변수를 줄 수가 없기 때문이죠.
람다식과 외부 메서드
람다식은 메서드의 내부에 작성해서 사용할 수 있습니다. 그렇기에 메서드 내에 메서드가 선언되는 구조처럼 보일 수 있습니다. 람다식은 외부 클래스에서는 내부 클래스와 동일하게 처리되기 때문에 메서드를 접근하는 데에는 제약이 없습니다.
publicclassTestLambda{publicvoidouter(int n){ String outer ="외부 메서드"; FuncInterface func =()->{ System.out.println("out 지역 변수: "+ outer);// n = 20; System.out.println("out 매개 변수 num: "+ n);}; func.execute();}publicstaticvoidmain(String[] args){ TestLambda tl =newTestLambda(); tl.outer(30);}}
이 예제를 보시면 중간에 주석이 쳐져 있는 곳을 보실 수 있습니다. 람다식의 외부 메서드인 outer의 매개 변수인 n 은 모두 final로 설정되어 있기에 참조만 가능합니다. 저 주석을 풀게 된다면 오류가 뜨는 것을 보실 수 있습니다.
Local variable n defined in an enclosing scope must be final or effectively final
이런 에러가 뜨는데 이것은 "범위 내의 지역변수 n 은 final이어야 한다" 라는 뜻을 가지고 있습니다. 바꿀 수 없다는 거죠. outer 변수 또한 마찬가지입니다. 당연히도 내부 클래스와 같은 개념이기에 해당되는 내용입니다. 일반적인 메서드
에서는 이렇지 않습니다.
메서드 참조
메서드 참조에 대한 형식을 알아보도록 하겠습니다. 우선 ::라는 예약어를 사용합니다. 형식을 이렇습니다.
이번에는 print라는 메서드를 추가하였습니다. dispose()라는 함수 대신 print라는 함수를 넣었습니다. class::method가 있어야 하기 때문에 this를 사용하여 클래스 자기 자신을 칭했습니다. 결과는 이렇습니다.
누르면 팝업창이 뜨는 것을 볼 수 있습니다. 간단하지요?
이번에는 제가 하다가 생각이 난 것입니다. 우선 사용하는 방식이 몇 가지 더 있습니다.
Type exam =(x,y)-> x > y ? x : y;
이 소스코드는 람다식을 사용한 if else 문입니다. ?는 if 문을 상징합니다. ?를 기준으로 앞은 조건문 뒤는 true일 시 전자 리턴 false일 시 후자를 리턴합니다. 이것을 보고 생각난 것이 boolean으로 메서드를 생성하고 그 안에 코딩을 해서 true or false를 리턴 시키는 방식을 사용하면 이러한 소스코드가 나오게 됩니다.
interfaceTest{ int testInter();}publicclassTestLambda{publicstaticvoidmain(String[] args){ Test func =()->b1()?10:20; System.out.println(func.testInter());}publicstatic boolean b1(){returntrue;}public boolean b2(){returnfalse;}}
약간 이런 식으로 true false를 구분해놓는 알고리즘을 짜고 반환값도 그에 맞는 값을 정해주면 간편하고 쉽게 사용할 수 있지 않을까 하는 생각이 듭니다. 좋은 로직이 될 수도 있을 것 같은 느낌이 듭니다.
댓글