자바 - 함수적 인터페이스

안녕하세요, 미래의 자바 개발자 여러분! 오늘, 우리는 자바에서의 함수적 인터페이스의 세계로 흥미진진한 여정을 떠날 거예요. 프로그래밍에 새로운 사람이라도 걱정 마세요; 저는 이 개념을 단계별로 안내해 드릴 거예요, 마치 저의 수많은 학생들을 위해 all those years of teaching. 그럼, 커피 한 잔 (또는 좋아하는 음료)을 준비하고, 함께 빠르게 들어가죠!

Java - Functional Interfaces

함수적 인터페이스란 무엇인가요?

자신이 파티에 DJ로 배정되었다고 상상해 봅시다. 당신의 일은 간단합니다: 음악을 재생하면 됩니다. 음식을 제공하거나 장소를 장식하는 건 걱정하지 않아요. 자바에서 함수적 인터페이스는 그 DJ와 비슷합니다 - 하나의 구체적인 일을 잘 해내는 것이에요.

기술적으로는, 함수적 인터페이스는 정확히 하나의 추상 메서드를 포함하는 인터페이스입니다. 다른 메서드를 가질 수 있지만, 그들은 기본 메서드이거나 정적 메서드여야 합니다. 단일 추상 메서드는 함수적 인터페이스에 "함수적" 성격을 더해줍니다.

예제 1: 간단한 함수적 인터페이스

@FunctionalInterface
interface Greeter {
void greet(String name);
}

이 예제에서, Greeter는 함수적 인터페이스입니다. 하나의 추상 메서드 greet 만 가지고 있으며, Stirng 파라미터를 받고 아무것도 반환하지 않습니다 (void).

@FunctionalInterface 어노테이션

우리의 예제에서 @FunctionalInterface 어노테이션을 발견했을 거예요. 이것은 인터페이스에 "DJ" 배지를 달는 것과 같아요. 자바에게 "이 인터페이스는 함수적이야!"라고 말합니다. 우리가 실수로 다른 추상 메서드를 추가하면, 자바는 에러를 주어 함수적 성격을 유지하게 도와줍니다.

함수적 인터페이스 사용법

이제 함수적 인터페이스가 무엇인지 알았으니, 어떻게 사용할 수 있는지 볼 차례입니다. 함수적 인터페이스의 가장 멋진 점 중 하나는 lambda 표현식과 함께 사용할 수 있다는 것입니다. lambda 표현식은 메서드를 짧게 쓰는 방법입니다.

예제 2: 함수적 인터페이스를 Lambda 표현식으로 사용

public class GreeterTest {
public static void main(String[] args) {
Greeter friendlyGreeter = (name) -> System.out.println("Hello, " + name + "! How are you?");
friendlyGreeter.greet("Alice");

Greeter formalGreeter = (name) -> System.out.println("Good day, " + name + ". I hope you're well.");
formalGreeter.greet("Mr. Smith");
}
}

이 예제에서, 우리는 Greeter 인터페이스를 사용하여 두 가지 다른 Greeter를 만들고 있습니다. lambda 표현식 (name) -> ...greet 메서드를 즉시 구현하는 것입니다. 두 가지 다른 파티에 두 가지 다른 DJ를 고용한 것과 같아요!

이 코드를 실행하면 다음과 같은 출력이 나옵니다:

Hello, Alice! How are you?
Good day, Mr. Smith. I hope you're well.

자바에서의 함수적 인터페이스 유형

자바는 우리의 삶을 더 쉽게 만들기 위해 여러 개의 내장 함수적 인터페이스를 제공합니다. 몇 가지 가장 일반적으로 사용되는 것들을 살펴보죠:

1. Predicate

Predicate<T> 인터페이스는 하나의 인수에 대한 부울 값을 가지는 함수를 사용합니다. 예스或노에 답할 수 있는 질문과 같아요.

import java.util.function.Predicate;

public class PredicateExample {
public static void main(String[] args) {
Predicate<Integer> isAdult = age -> age >= 18;

System.out.println("20은 어른의 나이입니까? " + isAdult.test(20));
System.out.println("15은 어른의 나이입니까? " + isAdult.test(15));
}
}

이것은 다음과 같은 출력을 내줍니다:

20은 어른의 나이입니까? true
15은 어른의 나이입니까? false

2. Function<T,R>

Function<T,R> 인터페이스는 하나의 인수를 받고 결과를 생성하는 함수를 나타냅니다. 무언가를 받아서 무언가를 내는 기계와 같아요.

import java.util.function.Function;

public class FunctionExample {
public static void main(String[] args) {
Function<String, Integer> stringLength = str -> str.length();

System.out.println("'Hello'의 길이: " + stringLength.apply("Hello"));
System.out.println("'Java is awesome'의 길이: " + stringLength.apply("Java is awesome"));
}
}

이것은 다음과 같은 출력을 내줍니다:

'Hello'의 길이: 5
'Java is awesome'의 길이: 16

3. Consumer

Consumer<T> 인터페이스는 하나의 입력 인수를 받고 결과를 반환하지 않는 연산을 나타냅니다. 데이터를 소비하지만 아무것도 생성하지 않는 블랙홀과 같아요.

import java.util.function.Consumer;

public class ConsumerExample {
public static void main(String[] args) {
Consumer<String> printer = message -> System.out.println("프린팅: " + message);

printer.accept("Hello, Functional Interface!");
printer.accept("Java is fun!");
}
}

이것은 다음과 같은 출력을 내줍니다:

프린팅: Hello, Functional Interface!
프린팅: Java is fun!

4. Supplier

Supplier<T> 인터페이스는 결과를 제공하는 공급자를 나타냅니다. 아무 인수도 받지 않지만 값이 생성됩니다. 무언가를 넣지 않고도 무언가를 주는 자동 판매기와 같아요.

import java.util.function.Supplier;
import java.util.Random;

public class SupplierExample {
public static void main(String[] args) {
Supplier<Integer> randomNumberSupplier = () -> new Random().nextInt(100);

System.out.println("랜덤 숫자: " + randomNumberSupplier.get());
System.out.println("다른 랜덤 숫자: " + randomNumberSupplier.get());
}
}

이것은 0부터 99 사이의 두 개의 랜덤 숫자를 출력합니다, 예를 들어:

랜덤 숫자: 42
다른 랜덤 숫자: 73

자바 8 이전에 기존의 함수적 인터페이스

자바 8가 함수적 인터페이스 개념을 도입하기 전에는 자바는 몇 가지 해당 정의에 맞는 인터페이스가 있었습니다. 이들은 주로 이벤트 처리와 동시 프로그래밍에 사용되었습니다. 몇 가지 예제를 살펴보죠:

1. Runnable

Runnable 인터페이스는 자바의 초기 날부터 존재하고 있습니다. 이는 쓰레드를 생성하는 데 일반적으로 사용됩니다.

public class RunnableExample {
public static void main(String[] args) {
Runnable helloRunnable = () -> System.out.println("쓰레드에서 인사합니다!");
new Thread(helloRunnable).start();
}
}

이것은 다음과 같은 출력을 내줍니다:

쓰레드에서 인사합니다!

2. Comparator

Comparator 인터페이스는 객체에 대한 사용자 정의 정렬을 정의하는 데 사용됩니다.

import java.util.Arrays;
import java.util.Comparator;

public class ComparatorExample {
public static void main(String[] args) {
String[] names = {"Alice", "Bob", "Charlie", "David"};

Comparator<String> lengthComparator = (s1, s2) -> s1.length() - s2.length();

Arrays.sort(names, lengthComparator);

System.out.println("길이별로 정렬된 것: " + Arrays.toString(names));
}
}

이것은 다음과 같은 출력을 내줍니다:

길이별로 정렬된 것: [Bob, Alice, David, Charlie]

결론

축하합니다! 여러분은 자바에서의 함수적 인터페이스의 세계로 첫 걸음을 내딛었습니다. 우리는 그것이 무엇인지, 어떻게 사용하는지, 그리고 몇 가지 일반적인 유형을 살펴보았습니다. 기억해 주세요, 함수적 인터페이스는 자바 도구 상자에 있는 특수한 도구입니다. 그들은 여러분의 코드를 더 깔끔하고 표현력 있는 코드로 작성하는 데 도와줍니다.

자바 여정을 계속할 때, 함수적 인터페이스의 사용 사례를 더 많이 찾아보십시오. 그들은 특히 스트림과 컬렉션을 작업할 때 매우 강력합니다. 이는 우리가 미래의 수업에서 다룰 내용입니다.

계속 연습하고, 호기심을 지켜주시고, 가장 중요한 것은 코딩하는过程에서 즐기세요! 자바는 넓고 흥미로운 언어이며, 여러분은 이미 그를 마스터하는 길에 나아가고 있습니다. 다음 번에 뵙겠습니다, 즐거운 코딩 하세요!

Credits: Image by storyset