Java에서 함수를 매개 변수로 전달하려면 어떻게 해야 합니까?
자바에서는 어떤 함수를 다른 함수의 인수로 넘길 수 있나요?
Java 8 이상
Java 8+ lamda 식을 사용하는 경우 추상 메서드(SAM 유형이라고도 함)가 하나뿐인 클래스 또는 인터페이스가 있는 경우 다음과 같습니다.
public interface MyInterface {
String doSomething(int param1, String param2);
}
MyInterface가 사용되는 모든 위치에서 람다 식을 대체할 수 있습니다.
class MyClass {
public MyInterface myInterface = (p1, p2) -> { return p2 + p1; };
}
예를 들어, 새 스레드를 매우 빠르게 생성할 수 있습니다.
new Thread(() -> someMethod()).start();
또한 메서드 참조 구문을 사용하여 보다 깔끔하게 만듭니다.
new Thread(this::someMethod).start();
람다 식을 사용하지 않으면 마지막 두 가지 예는 다음과 같습니다.
new Thread(new Runnable() { someMethod(); }).start();
Java 8 이전 버전
에서 「랩」하는 것입니다.를 들어, 「이라고 하는 패턴입니다.Callable
콜러블
public T myMethod(Callable<T> func) {
return func.call();
}
특정 용도에 맞는 인터페이스를 작성하는 것이 가장 좋습니다.호출 가능을 선택한 경우 위의 T를 String과 같은 원하는 유형의 반환 값으로 대체합니다.
아래의 코멘트에 대한 답변은 다음과 같습니다.
public int methodToPass() {
// do something
}
public void dansMethod(int i, Callable<Integer> myFunc) {
// do something
}
익명의 내적 계급을 사용하여 호출합니다.
dansMethod(100, new Callable<Integer>() {
public Integer call() {
return methodToPass();
}
});
이것은 '꼼수'가 아니라는 것을 명심해라.이것은 java의 기본 개념상 함수 포인터와 동등합니다.
이를 위해 Java 리플렉션을 사용할 수 있습니다.이 메서드는 java.lang.reflect 인스턴스로 표시됩니다.방법.
import java.lang.reflect.Method;
public class Demo {
public static void main(String[] args) throws Exception{
Class[] parameterTypes = new Class[1];
parameterTypes[0] = String.class;
Method method1 = Demo.class.getMethod("method1", parameterTypes);
Demo demo = new Demo();
demo.method2(demo, method1, "Hello World");
}
public void method1(String message) {
System.out.println(message);
}
public void method2(Object object, Method method, String message) throws Exception {
Object[] parameters = new Object[1];
parameters[0] = message;
method.invoke(object, parameters);
}
}
람다 식
jk.의 뛰어난 답변에 더해 Lambda Expressions(Java 8에서)를 사용하여 메서드를 보다 쉽게 전달할 수 있습니다.일단 배경부터 말씀드릴게요.기능 인터페이스는 추상적인 메서드가1개밖에 없는 인터페이스입니다만, 임의의 수의 디폴트 메서드(Java 8의 신기능)와 스태틱메서드를 포함할 수 있습니다.람다 식을 사용하지 않을 경우 불필요한 구문을 모두 사용하지 않고도 람다 식을 통해 추상 메서드를 신속하게 구현할 수 있습니다.
람다 표현식 없음:
obj.aMethod(new AFunctionalInterface() {
@Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
람다 식 사용 시:
obj.aMethod(i -> i == 982);
다음은 Lambda Expressions에 대한 Java 튜토리얼에서 발췌한 것입니다.
람다 식 구문
람다 식은 다음과 같이 구성됩니다.
괄호로 둘러싸인 형식 파라미터의 쉼표로 구분된 리스트.CheckPerson.test 메서드에는 Person 클래스의 인스턴스를 나타내는 파라미터 p가 1개 포함되어 있습니다.
참고: 람다 식에서 모수의 데이터 유형을 생략할 수 있습니다.또한 파라미터가1개밖에 없는 경우에는 괄호를 생략할 수 있습니다.예를 들어, 다음 람다 식도 유효합니다.p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25
토큰 '''는
->
단일 식 또는 문 블록으로 구성된 본문.이 예에서는 다음 식을 사용합니다.
p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25
하나의 식을 지정하면 Java 런타임은 식을 평가한 다음 해당 값을 반환합니다.또는 return 문을 사용할 수 있습니다.
p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; }
반환문은 식이 아닙니다. 람다 식에서는 문을 중괄호({})로 묶어야 합니다.단, void 메서드 호출을 괄호로 묶을 필요는 없습니다.예를 들어, 다음은 유효한 람다 식입니다.
email -> System.out.println(email)
람다 표현식은 메서드 선언과 매우 유사합니다. 람다 표현식은 익명 메서드(이름 없는 메서드)로 간주할 수 있습니다.
다음은 람다 식을 사용하여 메서드를 "통과"하는 방법입니다.
주의: 새로운 표준 기능 인터페이스를 사용합니다.
class A {
public static void methodToPass(int i) {
// do stuff
}
}
import java.util.function.IntConsumer;
class B {
public void dansMethod(int i, IntConsumer aMethod) {
/* you can now call the passed method by saying aMethod.accept(i), and it
will be the equivalent of saying A.methodToPass(i) */
}
}
class C {
B b = new B();
public C() {
b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here
}
}
위의 예는 연산자를 사용하여 더욱 단축할 수 있습니다.
public C() {
b.dansMethod(100, A::methodToPass);
}
Java 8 덕분에 함수를 메서드에 전달하기 위해 다음 단계를 수행할 필요가 없습니다. 이것이 람다를 위한 것입니다. Oracle의 Lambda Expression 튜토리얼을 참조하십시오.이 투고의 나머지 부분에서는, 이 기능을 실장하기 위해서, 불경기의 시대에 무엇을 할 필요가 있었는지 설명합니다.
일반적으로 하나의 메서드로 어떤 인터페이스를 사용한다고 선언한 후 해당 인터페이스를 구현하는 개체를 전달합니다.예를 들어 commons-collections에서는 Closure, Transformer 및 Predicate의 인터페이스와 이러한 구현을 전달하는 메서드가 있습니다.Guava는 새롭게 개선된 공통 컬렉션으로, 동등한 인터페이스를 찾을 수 있습니다.
예를 들어 commons-collections에는 org.apache.commons.collections가 있습니다.Collection Utils는 전달된 객체를 랜덤으로 선택하는 많은 정적 메서드를 가지고 있으며, 이 시그니처에 의해 호출된 객체가 존재합니다.
static boolean exists(java.util.Collection collection, Predicate predicate)
인터페이스 Predicate를 구현하는 객체를 취득합니다.즉, 객체를 취득하고 부울을 반환하는 메서드가 필요합니다.
그래서 이렇게 부를 수 있어요.
CollectionUtils.exists(someCollection, new Predicate() {
public boolean evaluate(Object object) {
return ("a".equals(object.toString());
}
});
이 값은 true 또는 false로 반환됩니다.someCollection
에는 술어가 true를 반환하는 객체가 포함되어 있습니다.
어쨌든, 이것은 단지 하나의 예에 불과하고, 공유 수집은 시대에 뒤떨어진 것이다.나는 단지 과바의 동등한 것을 잊었다.
자바는 폐쇄를 잘 지원한다.기능을 지원하지 않기 때문에 폐쇄에 익숙한 구문은 훨씬 더 어색하고 부피가 커집니다. 수업에서 모든 것을 메서드로 마무리해야 합니다.예를들면,
public Runnable foo(final int x) {
return new Runnable() {
public void run() {
System.out.println(x);
}
};
}
Runnable 개체를 반환합니다.run()
method "오버"는x
1등급 기능 및 폐쇄를 지원하는 다른 언어처럼 통과되었습니다.
명령어 pattern that@jk.mentioned를 사용하여 반환 유형을 추가했습니다.
public interface Callable<I, O> {
public O call(I input);
}
이것은 꽤 오래된 포스트라는 것을 알지만, 조금 더 간단한 해결책이 하나 더 있습니다.다른 클래스를 생성하여 추상화할 수 있습니다.다음으로 Abstract 메서드에 원하는 이름을 붙입니다.원래 클래스에서 새 클래스를 매개 변수로 사용하는 메서드를 만듭니다. 이 메서드에서는 추상 메서드를 호출합니다.이렇게 생겼을 거예요.
public class Demo {
public Demo(/.../){
}
public void view(Action a){
a.preform();
}
/**
* The Action Class is for making the Demo
* View Custom Code
*/
public abstract class Action {
public Action(/.../){
}
abstract void preform();
}
}
이렇게 클래스 내에서 메서드를 호출할 수 있습니다.
/...
Demo d = new Demo;
Action a = new Action() {
@Override
void preform() {
//Custom Method Code Goes Here
}
};
/.../
d.view(a)
내가 말했듯이 나는 그것이 오래되었다는 것을 알지만 이 방법이 조금 더 쉽다고 생각한다.도움이 됐으면 좋겠다.
Java는 아직 폐쇄를 지원하지 않습니다.그러나 JVM에서 실행되어 폐쇄를 지원하는 Scala 및 Groovy와 같은 다른 언어도 있습니다.
언급URL : https://stackoverflow.com/questions/4685563/how-to-pass-a-function-as-a-parameter-in-java
'source' 카테고리의 다른 글
Vue 스타일 구성 요소에서 입력 유형 변경[체크박스]이 작동하지 않음 (0) | 2022.08.01 |
---|---|
Vuex에서 내부 작업을 호출하는 방법 (0) | 2022.08.01 |
Vue.js - Ajax 호출에서 컴포넌트를 로드합니다. (0) | 2022.08.01 |
vuejs3/vee-validate 4 app get vuex object의 제출 방법은 어떻게 됩니까? (0) | 2022.08.01 |
GNU99와 C99(Clang)의 차이점은 무엇입니까? (0) | 2022.08.01 |