본문 바로가기

Basic Grammar/Java

함수형 인터페이스

인터페이스 MyFunction은 메서드 max를 가진다.

 

 

 

익명클래스 선언과 객체 생성을 동시에 ( 오버라이딩 중 )

( new 조상클래스(or 인터페이스) {멤버들 선언}

 

함수형인터페이스가 있으므로 new Object() 대신 new MyFunction()을 사용

하지만 이제 max라는 메서드를 가지므로 f.max로 호출가능

 

여기서 메서드 대신에 람다식으로 바꿀 수 있다.

 

( 함수형 인터페이스 타입의 참조변수로 람다식을 참조할 수 있다.)

= MyFunction 타입의 참조변수 f 로 람다식 참조할 수 있다.

 

-> 람다식 다룰 수 있다. ( 함수형 인터페이스는 람다식 다루기 위해 사용)

함수형 인터페이스라고 @FunctionalInterface  붙혀주면 만약 추상메서드 두 개 작성 시 에러 띄워줌

 

인터페이스의 모든 메서드는 모두 public abstract 이므로 생략가능

 

15줄 부터 함수형 인터페이스 작성 후 4줄에 구현한다. 이 때 max 메서드는 인터페이스에서 public이므로 오버라이딩된 max는 public 생략불가 ( default가 되기 때문 )

 

 

 

 

람다식에서도 언급했지만 람다식은 익명객체이므로 함수형 인터페이스의 참조변수로 받을 수 있다.

 

 

 

 

추상 메서드와 람다식은 입출력이 같아야 한다. ( 천천히 생각해보기 )

-> 07.29 에 다시보니까 걍 당연한 소리 ㅋㅋ

 

# 중요 # 람다식 활용

 

 

 

 

 

# 결론 : 함수형 인터페이스의 참조 변수 = 람다식

 

 

 

----------------------------------------------------------------------------------------------------------

 

 

최근에 Spring이 제공하는 유틸성 클래스는 모두 abstract로 선언되어 있는 것을 볼 수 있습니다. 아마 객체의 생성을 방지하기 위한 의도였을 것 같은데, 과연 추상 클래스나 인터페이스는 실제로 객체를 생성하는 것이 불가능한지 살펴보도록 하겠습니다.

 

 

 

1. 인터페이스와 추상 클래스는 진짜 객체 생성이 불가능한가? 익명 객체(Anonymous Object)로 객체 생성하기


[ 인터페이스와 추상 클래스는 진짜 객체 생성이 불가능한가? ]

예를 들어 다음과 같은 Animal 추상 클래스가 있다고 가정을 하자.

public abstract class Animal {
    
    abstract void bark();
    
}

 

 

우리는 추상클래스에 대해 평소처럼 객체를 생성하려고 하면 에러가 발생하게 된다. 에러 내용을 분석해보면 Animal이 추상클래스이기 때문에 객체로 인스턴스화 할 수 없다는 내용이다.

 

 

 

 

자바에서 추상 클래스나 인터페이스를 객체로 만들 수 없게 해둔 이유는 메소드의 구현체가 존재하지 않기 때문이다. 그렇다면 추상 클래스나 인터페이스를 객체로 만드는 동시에 메소드를 구현하면 어떨까? 이에 대해 살펴보도록 하자.

 

 

 

 

[ 익명 객체(Anonymous Object)로 객체 생성하기 ]

자바에서는 일시적으로 한번만 사용이 필요할 때 사용하도록 익명 객체를 제공하고 있다. 익명 객체는 말 그대로 이름이 없는 객체를 의미하며, 일반적으로 생성한 후에 바로 다른 메소드나 클래스의 파라미터로 넘겨줄 때 사용된다.

추상 클래스나 인터페이스의 경우에도 익명 객체를 생성하면서 동시에 메소드를 오버라이딩해준다면 객체로 만들 수 있다. 다음과 같이 위의 Animal 클래스의 익명 객체를 만들수 있다.

@Test
void barkTest() {
    Animal anonymousObject = new Animal() {

        @Override
        public void bark() {
            System.out.println("bark");
        }
    };

    anonymousObject.bark();
    System.out.println(anonymousObject.getClass());
}

 

 

위와 같이 추상 클래스나 인터페이스를 익명 객체로 생성가능한 이유는 객체를 생성하면서 메소드를 오버라이딩 해주었기 때문이다.

그렇다면 익명 객체의 클래스는 어떻게 될까? 위에서 출력한 익명 객체의 클래스 정보를 출력해보면 다음과 같이 출력이 된다.

 

 

 

 

일반적으로 클래스 정보에서 $는 내부 클래스 또는 이너 클래스를 의미한다. 즉, 위와 같이 객체를 생성할 때 선언했던 내용들은 해당 클래스의 내부 클래스에 생성되며, 내부 클래스는 이름이 없으므로 임의로 1, 2, 3 ... N 순서대로 값이 부여되는 것이다.

익명 객체를 만드는 작업은 해당 클래스의 이너 클래스를 생성하는 것이므로 추상 클래스나 인터페이스도 객체로 생성이 가능한 것이다.

 

 

 

 

 

그러므로 추상 클래스나 인터페이스는 항상 객체로 만들어질 수 없다는 것은 올바르지 못한 표현이다. 일반적으로 객체로 만들어질 수 없는 것은 맞지만, 특수하게 익명 객체를 사용하면 인스턴스화할 수 있다. 스프링에서는 이러한 익명 객체 방식이 많이 사용되어 이러한 구조를 템플릿 메소드 패턴이라고도 하는데, JdbcTemplate과 같이 *Template으로 선언된 클래스들은 모두 이러한 익명 객체를 기반으로하는 템플릿 메소드 패턴이 적용되었다고 이해하면 된다. 참고로 템플릿 메소드 패턴은 GoF 디자인 패턴이 아니고, 스프링에서 자주 사용되어 스프링에서만 불리는 디자인 패턴 이름이다.

 

 

 

출처 : https://mangkyu.tistory.com/227?category=872426

 

 

 

 

 

'Basic Grammar > Java' 카테고리의 다른 글

자바 9강 - 자바코드 실행원리  (0) 2022.07.20
자바의 레퍼런스 타입  (0) 2022.07.17
람다식  (0) 2022.07.16
Stream  (0) 2022.07.10
JAVA의 객체지향 - static  (0) 2022.06.19
Recent Posts
Popular Posts
Recent Comments