1. 구현 메서드의 약식 표현
- 함수형 인터페이스의 객체 생성 과정에서 익명 이너 클래스를 이용한 객체 생성 방식의 축약된 표현을 제공
- 직접 추상 메서드를 구현하는 형태
- 익명 이너 클래스 내부의 구현 메서드를 단순히 축약해 표현한 형태
package OOP;
interface A {
//입력 x, 리턴 x
void method1();
}
interface B{
//입력 o, 리턴 x
void method2(int a);
}
interface C {
//입력 x, 리턴 o
int method3();
}
interface D {
//입력 o, 리턴 o
double mehtod4(int a, double b);
}
class OOP {
public static void main(String[] args) {
//인터페이스의 함수 구현 -> 람다식
//1.입력 x, 리턴 x
//1-1 익명 이너 클래스 방식
A a1 = new A() {
//override
public void method1() {
System.out.println("입력 x,리턴 x 함수");
}
};
//1-2 람다식 표현
A a2 = () -> System.out.println("입력 x, 리턴 x 함수");
//2. 입력 o, 리턴 x
//2-1 익명 이너 클래스 방식
B b1 = new B() {
//override
public void method2(int a) {
System.out.println("입력 o, 리턴 x함수");
}
};
//2-2 람다식 표현
B b2 = a -> System.out.println("입력 o, 리턴 x함수");
//3. 입력 x, 리턴 o
//3-1 익명 이너 클래스 방식
C c1 = new C() {
//override
public int method3() {
return 4;
}
};
//3-2 람다식 표현
C c2 = ()-> 4;
//4.입력 o, 리턴 o
//4-1 익명 이너 클래스 방식
D d1 = new D() {
//override
public double method4(int a, double b) {
return a+b;
}
};
//4-2 람다식 표현
D d2 = (a,b) -> a+b;
}
}
2. 메서드 참조
- 추상 메서드를 직접 구현하는 대신, 이미 구현이 완료된 메서드를 참조
- 인스턴스 메서드 참조 / 정적 메서드 참조
1) 정의돼 있는 인스턴스 메서드 참조
- 인스턴스 메서드를 참조하기 이해서는 먼저 인스턴스 메서드가 사용할 수 있는 상태가 돼야 하므로 객체 먼저 생성
- 객체 생성 후 '객체 참조 변수 :: 인스턴스 메서드명' 작성
클래스 객체 :: 인스턴스 메서드명
ex)
-abc() 추상 메서드 하나를 갖는 함수형 인터페이스 A와 인스턴스 메서드 bcd()를 갖고 있는 B클래스 정의
-구현한 abc() 메서드에는 B 클래스 객체를 생성해 인스턴스 메서드 bcd()를 호출
- abc() 메서드를 호출하면 B 객체 멤버인 bcd()를 호출하는 것
-> abc()는 bcd()와 동일
- bcd()는 이미 완성된 인스턴스 메서드이므로 abc()가 bcd()와 동일하다는 사실만 알려주면 됨
-> 람다식의 인스턴스 메서드 참조
B b = new B();
A a = b::bcd;
-> 'A 인터페이스 내부의 abc() 메서드는 참조 변수 b 객체 내부의 인스턴스 메서드 bcd()와 동일하다'
-abc()가 bcd()를 참조하기 이해서는 리턴 타입과 매개변수의 타입이 반드시 동일해야함
package OOP;
interface A {
void abc();
}
class B{
void bcd() {
System.out.println("메서드");
}
}
class OOP {
public static void main(String[] args) {
//1. 익명 이너 클래스
A a1 = new A() {
//override
public void abc() {
B b = new B();
b.bcd();
}
};
//2.람다식으로 표현
A a2 = () -> {
B b = new B();
b.bcd();
};
//3.정의된 인스턴스 메서드 참조
B b = new B();
A a3 = b::bcd;
a1.abc();
a2.abc();
a3.abc();
}
}
2) 자바가 제공하는 인스턴스 메서드 참조
- 내부에 void abc(int k) 추상 메서드를 가진 함수형 인터페이스 A
- 람다식 및 익명 이너 클래스로 구현한 abc() 메서드는 입력매개변수를 그대로 전달해 System.out.println()만을 호출
-> abc()는 System.out.println()와 항상 동일한 동작을 수행
- System.out 자체가 객체이므로 다음과 같이 간단하게 작성 가능
A a = System.out :: println;
- '인터페이스 A의 추상 메서드인 abc()는 System.out.println()을 참조하라'
-abc()를 호출하면 대신 System.out.println()을 호출하라
package OOP;
interface A {
void abc(int k);
}
public class Ramda {
public static void main(String[] args) {
//1.익명 이너 클래스
A a1 = new A() {
//override
public void abc(int k) {
System.out.println(k);
}
};
//2.람다식으로 표현
A a2 = (int k) -> {
System.out.println(k);
};
//3. 인스턴스 메서드 참조
A a3 = System.out :: println;
a1.abc(3);
a2.abc(3);
a3.abc(3);
}
}
3) 정의돼 있는 정적 메서드 참조
-'클래스명 :: 정적 메서드명'으로 메서드 참조
클래스명 :: 정적 메서드명
- 정적 메서드는 객체 생성 없이 클래스명으로 바로 사용 가능
- 정적 메서드의 참조를 위해서는 리턴 타입과 입력매개변수 타입이 동일해야함
ex)
-abc() 추상 메서드 1개를 갖는 함수형 인터페이스 A
- 정적 메서드 bcd()를 갖고 있는 B 클래스 정의
- 익명 이너 클래스 및 람다식을 이용해 인터 페이스 A 객체 생성 후 abc() 메서드 구현
- 구현한 abc() 메서드 내부에서는 B.bcd()와 같이 클래스 B의 정적 메서드만을 호출
-> abc() 메서드가 B.bcd()와 동일한 기능 수행
A a = B::bcd;
- '인터페이스 A의 객체를 생성할 때 구현해야 하는 abc() 메서드를 B.bcd()와 동일하게 하라'
package OOP;
interface A {
void abc();
}
class B {
static void bcd() {
System.out.println("메서드");
}
}
public class Ramda {
public static void main(String[] args) {
//1.익명 이너 클래스
A a1 = new A() {
//override
public void abc() {
B.bcd();
}
};
//2.람다식으로 표현
A a2 = ()-> {B.bcd();};
//3.정적 메서드 참조
A a3 = B::bcd;
a1.abc();
a2.abc();
a3.abc();
}
}
4) 첫 번째 매개변수로 전달된 객체의 인스턴스 메서드 참조
- 추상 메서드의 구현 과정에서 첫 번째 매개변수로 인스턴스 메서드를 포함하고 있는 객체를 함께 전달, 이후 전달된 객체의 인스턴스 메서드를 참조
- 객체가 첫 번째 매개변수로 전달되므로 따로 객체생성하는 과정은 필요 없음
클래스명 :: 인스턴스 메서드명
-> 정적 메서드와 참조 형태 같음 But , static 유무로 구별 가능
-> 정적 메서드 참조할 때는 추상 메서드와 참조 메서드의 입력 매개변수가 모두 동일
-> 전달된 객체의 메서들르 참조할 때는 추상메서드의 첫 번째 매개변수로 객체가 들어가기 때문에 참조 메서드보다 매개변수가 1개 더 많음
ex)
- abc(B b, int k)와 같이 2개의 매개변수를 입력받는 추상메서드를 포함한 인터페이스 A
- bcd(int k)와 같이 하나의 매개변수를 갖는 인스턴스 메서드를 포함한 클래스 B
- 익명 이너 클래스 및 람다식으로 인터페이스 A의 객체를 생성하는 과정에서 구현한 abc() 메서드에는
첫번째 매개변수로 넘어온 객체의 bcd() 메서드를 호출함
A a = B::bcd;
- abc(B b, int k)의 메서드는 첫 번째 매개변수 내부의 bcd() 메서드와 동일
package OOP;
interface A {
void abc(B b, int k);
}
class B {
void bcd(int k) {
System.out.println(k);
}
}
public class Ramda {
public static void main(String[] args) {
//1.익명 이너 클래스
A a1 = new A() {
//override
public void abc(B b, int k) {
b.bcd(k);
}
};
//2.람다식으로 표현
A a2 = (B b, int k)-> {b.bcd(k);};
//3.정적 메서드 참조
A a3 = B::bcd;
a1.abc(new B(), 3);
a2.abc(new B(), 3);
a3.abc(new B(), 3);
}
}
5) 자바가 제공하는 인스턴스 메서드 참조
package OOP;
interface A {
int abc(String str);
}
public class Ramda {
public static void main(String[] args) {
//1.익명 이너 클래스
A a1 = new A() {
//override
public int abc(String str) {
return str.length();
}
};
//2.람다식
A a2 = (String str) -> str.length();
//3.자바가 제공하는 인스턴스 메서드 참조
A a3 = String :: length;
System.out.println(a1.abc("안녕"));
System.out.println(a2.abc("안녕"));
System.out.println(a3.abc("안녕"));
}
}
3. 생성자 참조
1) 배열 생성자 참조
- 함수형 인터페이스에 포함된 추상 메서드가 배열의 크기를 입력매개변수로 하며, 특정 배열 타입을 리턴한다면 구현 메서드의 내부에는 반드시 new 자료형[]이 포함될 것임
- 추상 메서드의 구현 메서드가 new 자료형[]과 같이 배열 객체의 생성 기능만을 수행할 때는 람다식의 배열 생성자 참조 방법을 사용 가능
배열 타입 :: new
ex)
- 정수 1개를 입력매개변수로 갖고, int[] 배열 타입을 리턴하는 추상메서드를 포함하는 인터페이스 A
interface A {
int[] abc(int len);
}
-인터페이스 A의 객체를 익명 이너 클래스 및 람다식으로 작성
익명이너클래스
A a = new A() {
public int[] abc(int len) {
return new int[len];
}
};
람다식
A a = (len) -> new int[len];
-> new int[len]과 같이 new 키워드로 입력 매개변수로 전달받은 정수의 크기를 갖는 배열 객체만을 생성한 후 리턴
- 구현 메서드의 내용이 단순히 배열 객체를 생성할 때는 람다식의 배열 생성자 참조 방법 사용 가능
A a = int[] ::new;
-> 'abc(len)를 호출하면 len 크기를 갖는 int[]를 생성하는 new int[len]을 실행한 후 객체를 리턴하라'
2) 클래스 생성자 참조
- 인터페이스의 추상 메서드가 클래스 타입의 객체를 리턴할 때도 생성자 참조 사용 가능
- 추상 메서드를 구현할 때 new 생성자()와 같이 객체만을 생성해 리턴하면 클래스 생성자 참조 사용 가능
ex)
- 인터페이스 A는 B 타입을 리턴하는 추상 메서드 abc()를 갖고 있음
- 클래스 B에는 기본 생성자를 포함해 2개의 생성자가 정의
interface A {
B abc();
}
class B{
B(){} //첫번째 생성자
B(int k){} //두번째 생성자
}
- 인터페이스 A의 객체를 익명 이너 클래스와 람다식의 방법으로 작성
익명 이너 클래스
A a = new A() {
public B abc() {
return new B();
}
};
람다식
A a = () -> new B();
- > 객체를 생성할 때 구현한 abc() 메서드의 내부에는 new B()와 같이 클래스 B의 객체만을 생성해 리턴
- 클래스의 new 생성자를 참조할때
A a = B::new;
-> 'a.abc() 메서드를 호출하면 new B()를 실행해 객체를 생성하라'
- 생성자가 여러개일때 기본생성자와 다른 생성자를 호출해 객체 생성하는 방법
-> 인터페이스 A에 포함된 추상메서드의 매개변수에 따라 결정
interface A {
B abc(int k);
}
class B{
B(){} // 첫 번째 생성자
B(int k) {} // 두 번째 생성자
}
익명 이너 클래스로 인터페이스 A 객체 생성
A a = new A() {
public B abc(int k) {
return new B(k);
}
};
람다식으로 인터페이스 A 객체 생성
A a = (k) -> new B(k);
- >구현 메서드로 넘어온 매개변수를 그대로 입력매개변수로 갖는 생성자를 이용해 객체 생성
A a = B::new;
-> 'abc(k)를 호출하면 new B(k)를 실행하라'
'Java > 문법' 카테고리의 다른 글
18 - 1장 람다식 (0) | 2023.06.24 |
---|---|
17 - 6장 Queue<E> 컬렉션 인터페이스 (0) | 2023.06.19 |
17 - 5장 Stack<E> 컬렉션 클래스 (0) | 2023.06.19 |
17 - 4 장 Map<K,V> 컬렉션 인터페이스 (0) | 2023.06.18 |
17 - 3장 Set<E> 컬렉션 인터페이스 (2) (2) | 2023.06.18 |