|형식| 인터페이스명 객체변수명 = 람다식;
|람다식의 형식| (매개변수들...) -> {처리할 코드들;...}
이전 스레드 선언방법3번째가 익명클래스를 이용했다. Runnable의 추상메서드는 void run()하나이고 결국 함수적 인터페이스!
public class T01_LambdaTest {
public static void main(String[] args) {
// 람다식을 사용하지 않는경우
Thread th1 = new Thread(new Runnable() {
@Override
public void run() {
for(int i =1; i<=10; i++) {
System.out.println(i);
}
}
});
th1.start();
// 람다식을 사용하는 경우
Thread th2 = new Thread(()->{
for(int i =1; i<=10; i++) {
System.out.println("람다 - "+i);
}
});
th2.start();
}
}
기본형식 ) (자료형이름 매개변수명,...) -> {실행문들;...}
1) 매개변수의 '자료형이름'은 생략 할 수 있다
(int a) -> {System.out.println(a);}
(a) -> {System.out.println(a);}
2) 매개변수가 1개일 경우에는 괄호 '()'를 생략 할 수 있다.
(단, '자료형 이름'을 지정할 경우에는 괄호를 생략 할 수 없다)
a -> {System.out.println(a);}
3) '실행문'이 1개일 경우에는 '{}'를 생략 할 수 있다
(이때 문장의 끝을 나타내는 세미콜론(;)도 생략한다.)
a -> System.out.println(a)
4) 매개변수가 하나도 없으면 괄호’()’를 생략할 수 없다
() -> System.out.println("안녕");
5) 반환값이 있을 경우에는 return명령을 사용한다.
(a,b) -> { return a+b; }
(a,b) -> return a+b
6) 실행문에 return만 있을경우 return 명령과 ‘{}’를 생략할 수 있다
(a,b) -> a+b
인터페이스
// 함수적 인터페이스 => 추상메소드가 한개뿐인 인터페이스
@FunctionalInterface
public interface LambdaTestInterface1 {
// 반환값이 없고 매개변수도 없는 추상메소드 선언
public void test();
}
@FunctionalInterface
interface LambdaTestInterface2 {
// 반환값이없고 매개변수는 있는 추상메소드 선언
public void test(int a);
}
@FunctionalInterface
interface LambdaTestInterface3 {
// 반환값과 매개변수가 모두 있는 추상메소드 선언
public int test(int a, int b);
}
public class T02_LambdaTest {
public static void main(String[] args) {
// 람다식을 사용하지 않았을 경우
LambdaTestInterface1 lam1 = new LambdaTestInterface1() {
@Override
public void test() {
System.out.println("안녕하세요");
System.out.println("익명 구현 객체 방식입니다");
}
};
lam1.test(); //메서드 호출
LambdaTestInterface1 lam2 = () ->
System.out.println("반가워요\n람다식으로 처리하는 방식입니다");
lam2.test();
System.out.println("----------------------------------------------------");
LambdaTestInterface2 lam3 =
(int z) -> {
int result = z+100;
System.out.println("result = "+result);
};
lam3.test(30);
LambdaTestInterface2 lam4 =
z -> {
int result = z+300;
System.out.println("result = "+result);
};
lam4.test(60);
LambdaTestInterface2 lam5 =
z -> System.out.println("result = "+(z+500));
lam5.test(90);
System.out.println("---------------------------------");
LambdaTestInterface3 lam6 =
(int x, int y)-> {
int r = x+y;
return r;
};
int k = lam6.test(20, 50);
System.out.println("k = "+k);
LambdaTestInterface3 lam7 =
(x,y)-> {
return x+y;
};
k = lam7.test(80, 50);
System.out.println("k= "+k);
LambdaTestInterface3 lam8 =
(x,y) -> x+y;
k = lam8.test(100,200);
System.out.println("k = "+k);
LambdaTestInterface3 lam9 =
(x,y) -> x > y ? x : y;
k = lam9.test(100, 200);
System.out.println("k = "+k);
}
}
람다식 내부에서 사용되는 지역변수는 모두 final이어야 한다.
보통은 final을 붙이지 않으면 컴파일러가 자동으로 붙여준다
단, 지역변수의 값을 변경하는 식이 있을 경우에는 자동으로 final을 붙여주지 않는다
즉 익명객체 안에서 지역변수를 참조할때 그 지역변수는 final이어야만 참조가 가능하다!
원래 그냥 int로 선언해도 알아서final로 처리해주지만 만약 도중에 값을 바꾸는 내용이 있을경우 final로 바꿀 수 없으므로 컴파일오류가 뜬다.
public class T03_LambdaTest {
static int stVar = 9;
private String name = "aaa";
public void testMethod(final int temp) {
final int localVar = 50;
int kor = 100;
temp = 500; //error!
localVar = 2000; //error!
kor = 400;
// 람다식에서 지역변수 사용하기
LambdaTestInterface1 lam =
() -> {
System.out.println("tmep = "+temp);
System.out.println("localVar = "+localVar);
System.out.println("kor = "+kor); //error!
System.out.println("stVar = "+stVar);
System.out.println("this.name = "+this.name);
};
lam.test();
}
public static void main(String[] args) {
new T03_LambdaTest().testMethod(200);
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class T04_LambdaTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("홍길동");
list.add("이순신");
list.add("변학도");
//
for(String str : list) {
System.out.println(str);
}
//
list.forEach(new Consumer<String>() {
@Override
public void accept(String t) {
System.out.println(t);
}
});
// 람다식을 이용해 출력을 더 간단하게 표현 ( 알맹이는 위로 변해서 컴파일되는거 )
list.forEach((t) ->System.out.println(t));
}
}