Java8에서 void (void가 아닌) 메소드에 함수 유형을 지정하는 방법은 무엇입니까?
Java 8을 가지고 놀고 있습니다. 다음 스 니펫이 있습니다.
package test;
import java.util.*;
import java.util.function.*;
public class Test {
public static void myForEach(List<Integer> list, Function<Integer, Void> myFunction) {
list.forEach(functionToBlock(myFunction));
}
public static void displayInt(Integer i) {
System.out.println(i);
}
public static void main(String[] args) {
List<Integer> theList = new ArrayList<>();
theList.add(1);
theList.add(2);
theList.add(3);
theList.add(4);
theList.add(5);
theList.add(6);
myForEach(theList, Test::displayInt);
}
}
내가 시도 하는 메소드 참조를 사용하여 메소드 displayInt
를 메소드에 전달하는 것 myForEach
입니다. 컴파일러에서 다음과 같은 오류가 발생합니다.
src/test/Test.java:9: error: cannot find symbol
list.forEach(functionToBlock(myFunction));
^
symbol: method functionToBlock(Function<Integer,Void>)
location: class Test
src/test/Test.java:25: error: method myForEach in class Test cannot be applied to given ty
pes;
myForEach(theList, Test::displayInt);
^
required: List<Integer>,Function<Integer,Void>
found: List<Integer>,Test::displayInt
reason: argument mismatch; bad return type in method reference
void cannot be converted to Void
컴파일러는 그것을 불평합니다 void cannot be converted to Void
. myForEach
코드가 부여 할 서명에서 함수 인터페이스 유형을 지정하는 방법을 모르겠습니다 . 나는 단지의 반환 형식을 설명 수 있습니다 알고 displayInt
에 Void
다음 반환 null
. 그러나 다른 곳에서 전달하려는 방법을 사용할 수 있습니다. 그대로 쉬운 쉬운 방법 displayInt
이 있습니까?
잘못된 인터페이스 유형을 사용합니다. 경우이 함수 유형 은 매개 변수를 수신하고 리턴 값을 가지므로 적합하지 않습니다. 대신 컨슈머 (이전 명칭 블록) 를 사용해야합니다
함수 타입은
interface Function<T,R> {
R apply(T t);
}
그러나 소비자 유형은 다음과 같은 제품과 호환됩니다.
interface Consumer<T> {
void accept(T t);
}
따라서 소비자는 아무것도받지 않고 반환하지 않습니다. 그리고 이것이 당신이 원하는 것입니다.
예를 들어, 목록에 모든 요소를 표시 후 간단히 람다 식을 사용하여 소비자를 만들 수 있습니다.
List<String> allJedi = asList("Luke","Obiwan","Quigon");
allJedi.forEach( jedi -> System.out.println(jedi) );
위의 경우 람다 식은 변수를 받고 반환 값이 없음을 알 수 있습니다.
이제 람다 식 대신 메서드 참조를 사용하여이 형식의 소비를 만들려면 String을 받고 void를 반환하는 메서드가 필요합니다.
나는 방법 참조의 다른 유형을 사용하지만,이 경우 사용하여 객체 메소드 참조의의 포획을 이용 할 수 println
의 방법을 System.out
다음과 같이 객체 :
Consumer<String> block = System.out::println
아니면 간단히 할 수 있습니다
allJedi.forEach(System.out::println);
이 println
메서드는 accept
Consumer 의 메서드 와 마찬가지로 값을 수신하고 반환 유형이 void이므로 적절합니다 .
따라서 코드에서 메서드 서명을 다음과 같이 변경해야합니다.
public static void myForEach(List<Integer> list, Consumer<Integer> myBlock) {
list.forEach(myBlock);
}
그런 다음 다음을 수행하여 정적 메서드 참조를 사용하여 소비자를 만들 수 있어야합니다.
myForEach(theList, Test::displayInt);
궁극적으로 myForEach
메서드를 모두 제거 하고 간단히 다음을 수행 할 수도 있습니다.
theList.forEach(Test::displayInt);
일등 시민으로서의 기능에 대하여
사실 구조적 기능 유형이 언어에 추가되지 않기 때문에 Java 8은 일류 시민으로서 기능을 갖지 않을 것입니다. Java는 람다 식 및 메서드 참조에서 기능 인터페이스의 구현을 만드는 대체 방법을 제공합니다. 궁극적으로 람다 식과 메서드 참조는 개체 참조에 바인딩되므로 우리가 가진 것은 일류 시민으로서 개체뿐입니다. 중요한 것은 객체를 매개 변수로 전달하고 변수 참조에 바인딩하고 다른 메소드의 값으로 반환 할 수 있기 때문에 기능이 있다는 것입니다. 그러면 거의 비슷한 목적으로 사용됩니다.
인수를 취하지 않고 결과를 반환하지 않는 함수를 인수로 받아 들여야 할 때 (무효), 제 생각에는 다음과 같은 것을 갖는 것이 가장 좋습니다.
public interface Thunk { void apply(); }
코드 어딘가에. 내 함수형 프로그래밍 과정에서 'thunk'라는 단어는 이러한 함수를 설명하는 데 사용되었습니다. java.util.function에없는 이유는 내 이해를 초월합니다.
다른 경우에는 java.util.function에 내가 원하는 서명과 일치하는 것이 있더라도 인터페이스의 이름이 내 코드의 함수 사용과 일치하지 않을 때 항상 옳다고 느껴지지는 않습니다. Thread 클래스와 관련된 용어 인 'Runnable'과 관련하여 여기 다른 곳에서 언급 한 것과 비슷한 점이라고 생각합니다. 그래서 내가 필요한 서명이있을 수 있지만 여전히 독자를 혼란스럽게 할 수 있습니다.
반환 유형을 and Void
대신으로 설정void
return null
// Modify existing method
public static Void displayInt(Integer i) {
System.out.println(i);
return null;
}
또는
// Or use Lambda
myForEach(theList, i -> {System.out.println(i);return null;});
대신 소비자 인터페이스를 사용해야한다고 생각합니다 Function<T, R>
.
소비자는 기본적으로 값을 받아들이고 아무것도 반환하지 않도록 설계된 기능적 인터페이스입니다 (즉, void).
귀하의 경우 다음과 같이 코드의 다른 곳에 소비자를 만들 수 있습니다.
Consumer<Integer> myFunction = x -> {
System.out.println("processing value: " + x);
.... do some more things with "x" which returns nothing...
}
그런 다음 myForEach
코드를 아래 스 니펫으로 바꿀 수 있습니다 .
public static void myForEach(List<Integer> list, Consumer<Integer> myFunction)
{
list.forEach(x->myFunction.accept(x));
}
myFunction을 일류 객체로 취급합니다.
'IT' 카테고리의 다른 글
이해력은 이해 범위 이후에도 이름을 리 바인드합니다. (0) | 2020.07.20 |
---|---|
판매에 HTTP 상태 코드 201 반환 (0) | 2020.07.20 |
오류 :이 범위에서 'NULL'이 유효하지 않습니다. (0) | 2020.07.20 |
django : select_related와 get_object_or_404를 함께 사용 (0) | 2020.07.20 |
R을 사용하여 압축 된 데이터 파일 다운로드, 데이터 추출 및 가져 오기 (0) | 2020.07.20 |