파라미터로서의 Java 패스 메소드


277

참조로 메서드를 전달하는 방법을 찾고 있습니다. Java가 메소드를 매개 변수로 전달하지 않는다는 것을 이해하지만 대안을 원합니다.

인터페이스가 메소드를 매개 변수로 전달하는 대안이라고 들었지만 인터페이스가 참조로 메소드로 작동하는 방법을 이해하지 못합니다. 내가 올바르게 이해하면 인터페이스는 정의되지 않은 추상 메소드 집합입니다. 여러 가지 다른 메소드가 동일한 매개 변수를 사용하여 동일한 메소드를 호출 할 수 있기 때문에 매번 정의 해야하는 인터페이스를 보내고 싶지 않습니다.

내가 성취하고 싶은 것은 이와 비슷한 것입니다.

public void setAllComponents(Component[] myComponentArray, Method myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod(leaf);
    } //end looping through components
}

다음과 같이 호출되었습니다.

setAllComponents(this.getComponents(), changeColor());
setAllComponents(this.getComponents(), changeSize());

지금 내 솔루션은 추가 매개 변수를 전달하고 내부에서 스위치 케이스를 사용하여 적절한 방법을 선택하는 것입니다. 그러나이 솔루션은 코드 재사용 중에는 적합하지 않습니다.

비슷한 질문에 대한 이 답변 stackoverflow.com/a/22933032/1010868
Tomasz Gawel

답변:


233

편집 : Java 8부터 다른 답변 이 지적한 것처럼 람다 식은 훌륭한 솔루션 입니다. 아래 답변은 Java 7 및 이전 버전 용으로 작성된 것입니다 ...


명령 패턴을 살펴보십시오 .

// NOTE: code not tested, but I believe this is valid java...
public class CommandExample 
{
    public interface Command 
    {
        public void execute(Object data);
    }

    public class PrintCommand implements Command 
    {
        public void execute(Object data) 
        {
            System.out.println(data.toString());
        }    
    }

    public static void callCommand(Command command, Object data) 
    {
        command.execute(data);
    }

    public static void main(String... args) 
    {
        callCommand(new PrintCommand(), "hello world");
    }
}

편집 :피트 Kirkham가 지적 하는 사용하여이 일을 다른 방법이 방문자가 . 방문자 접근 방식은 조금 더 복잡합니다. 노드는 모두 acceptVisitor()방법을 사용하여 방문자를 인식 해야하지만 더 복잡한 객체 그래프를 통과 해야하는 경우 검사 할 가치가 있습니다.


2
@Mac-좋아! 이것은 사실상의 시뮬레이션 방법으로 일류 방법이없는 언어로 반복해서 등장하므로 기억할 가치가 있습니다.
Dan Vinton

7
명령 패턴 (객체에 메소드 호출에 대한 인수를 캡슐화 함)이 아닌 방문자 패턴 (컬렉션의 각 멤버에 적용된 함수에서 콜렉션에 대한 반복 조치를 분리)입니다. 구체적으로 인수를 캡슐화하지 않습니다. 이는 방문자 패턴의 반복 부분에 의해 제공됩니다.
피트 Kirkham

아니요, 방문을 이중 발송과 결합하는 경우 accept 메소드 만 필요합니다. 단일 방문자가있는 경우 위 코드와 정확히 같습니다.
피트 Kirkham

Java 8에서 ex.operS (String :: toLowerCase, "STRING")와 같을 수 있습니다. 좋은 기사를보십시오 : studytrails.com/java/java8/…
Zon

Pete Kirkham은 정확합니다. 코드가 Command 패턴이 아닌 Visitor 패턴을 구현하고 있습니다. OP가 필요로하는 것이 좋습니다. Pete가 말했듯이 인수를 캡슐화하지 않으므로 Command를 수행하지 않습니다. 인터페이스에는 매개 변수를받는 실행이 있습니다. 위키 백과는 그렇지 않습니다. 이것은 명령 패턴의 의도에 기본입니다. 첫 번째 단락에서 " 모든 정보를 캡슐화 합니다 ...이 정보에는 메서드 이름, 메서드를 소유 한 개체 및 메서드 매개 변수의 값 "이 포함 됩니다 .
ToolmakerSteve

73

Java 8에서는 이제 Lambda Expressions 및 Method References를 사용하여보다 쉽게 ​​메서드를 전달할 수 있습니다 . 첫째, 일부 배경 : 기능적 인터페이스는 하나의 추상 메소드를 가진 인터페이스이지만 여러 기본 메소드를 포함 할 수 있습니다 (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를 포함합니다.

    참고 : 람다 식에서 매개 변수의 데이터 형식을 생략 할 수 있습니다. 또한 매개 변수가 하나만 있으면 괄호를 생략 할 수 있습니다. 예를 들어 다음 람다 식도 유효합니다.

    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)

람다 식은 메서드 선언과 매우 비슷합니다. 람다 식은 이름이없는 메서드 인 익명의 메서드로 간주 할 수 있습니다.


람다 식을 사용하여 "메소드를 전달하는"방법은 다음과 같습니다.

interface I {
    public void myMethod(Component component);
}

class A {
    public void changeColor(Component component) {
        // code here
    }

    public void changeSize(Component component) {
        // code here
    }
}
class B {
    public void setAllComponents(Component[] myComponentArray, I myMethodsInterface) {
        for(Component leaf : myComponentArray) {
            if(leaf instanceof Container) { // recursive call if Container
                Container node = (Container)leaf;
                setAllComponents(node.getComponents(), myMethodInterface);
            } // end if node
            myMethodsInterface.myMethod(leaf);
        } // end looping through components
    }
}
class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), component -> a.changeColor(component));
        b.setAllComponents(this.getComponents(), component -> a.changeSize(component));
    }
}

다음 C과 같이 메소드 참조를 사용하면 클래스 를 조금 더 단축 할 수 있습니다.

class C {
    A a = new A();
    B b = new B();

    public C() {
        b.setAllComponents(this.getComponents(), a::changeColor);
        b.setAllComponents(this.getComponents(), a::changeSize);
    }
}

인터페이스에서 클래스 A를 상속해야합니까?
Serob_b

1
@Serob_b 아뇨. 메소드 참조로 전달하지 않는 한 ( ::연산자 참조 ) A가 무엇인지는 중요하지 않습니다. a.changeThing(component)void를 반환하는 한 원하는 명령문이나 코드 블록으로 변경할 수 있습니다.
모자와 사람

29

java.lang.reflect.Method개체를 사용하여 전화invoke


12
왜 그런지 모르겠습니다. 문제는 메서드를 매개 변수로 전달하는 것입니다.이 방법은 매우 유효한 방법입니다. 이것은 예쁘게 보이도록 여러 가지 예쁜 패턴으로 감쌀 수도 있습니다. 그리고 이것은 특별한 인터페이스가 필요없는 일반적인 것입니다.
Vinodh Ramasubramanian 2019

3
JavaScript fg에 안전을 입력 했습니까? 타입 안전은 논쟁이 아닙니다.
Danubian Sailor

13
문제의 언어가 가장 강력한 구성 요소 중 하나로서 유형 안전성을 유지할 때 유형 안전성은 어떻게 논쟁이되지 않습니까? Java는 강력한 유형의 언어이며 강력한 타이핑은 다른 컴파일 된 언어를 선택하는 이유 중 하나입니다.
Adam Parkin

21
"핵심 리플렉션 기능은 원래 컴포넌트 기반 애플리케이션 빌더 도구 용으로 설계되었습니다. [...] 일반적으로 런타임시 일반 애플리케이션에서 오브젝트에 반사적으로 액세스해서는 안됩니다." 항목 53 : Effective Java Second Edition의 리플렉션보다 인터페이스를 선호하십시오. - 즉 ;-) 자바의 창조자의 생각의 라인입니다
Wilhem Meignan

8
반사의 정당한 사용이 아닙니다. 나는 모든 공감대를 보게되어 무섭다. reflect는 일반적인 프로그래밍 메커니즘으로 사용되지 않았습니다. 다른 깨끗한 용액이 없을 때만 사용하십시오.
ToolmakerSteve

22

Java 8부터 메소드 가있는 Function<T, R>인터페이스 ( docs )가 있습니다.

R apply(T t);

이를 사용하여 함수를 다른 함수에 매개 변수로 전달할 수 있습니다. T는 함수의 입력 유형이고 R은 반환 유형입니다.

귀하의 예에서 Componenttype을 입력으로 사용하고 아무것도 반환하지 않는 함수를 전달해야합니다 Void. 이 경우 Function<T, R>Void 유형의 자동 박스가 없으므로 최선의 선택이 아닙니다. 찾고있는 인터페이스를 메소드와 함께 Consumer<T>( docs ) 라고합니다.

void accept(T t);

다음과 같이 보일 것입니다 :

public void setAllComponents(Component[] myComponentArray, Consumer<Component> myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { 
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } 
        myMethod.accept(leaf);
    } 
}

그리고 메소드 참조를 사용하여 호출합니다.

setAllComponents(this.getComponents(), this::changeColor);
setAllComponents(this.getComponents(), this::changeSize); 

동일한 클래스에서 changeColor () 및 changeSize () 메소드를 정의했다고 가정하십시오.


메소드가 둘 이상의 매개 변수를 승인하는 경우 BiFunction<T, U, R>입력 매개 변수의 유형 인 T와 U를 사용 하고 리턴 유형 인 R을 사용할 수 있습니다 . 또한 BiConsumer<T, U>두 개의 인수, 반환 유형 없음이 있습니다. 불행히도 3 개 이상의 입력 매개 변수의 경우, 직접 인터페이스를 작성해야합니다. 예를 들면 다음과 같습니다.

public interface Function4<A, B, C, D, R> {

    R apply(A a, B b, C c, D d);
}

19

먼저 매개 변수로 전달할 메소드로 인터페이스를 정의하십시오.

public interface Callable {
  public void call(int param);
}

메소드를 사용하여 클래스 구현

class Test implements Callable {
  public void call(int param) {
    System.out.println( param );
  }
}

// 그렇게 불러

Callable cmd = new Test();

이를 통해 cmd를 매개 변수로 전달하고 인터페이스에 정의 된 메소드 호출을 호출 할 수 있습니다.

public invoke( Callable callable ) {
  callable.call( 5 );
}

1
java가 많은 것을 정의했기 때문에 자신 만의 인터페이스를 만들 필요는 없습니다. docs.oracle.com/javase/8/docs/api/java/util/function/…
Slim

@slim 흥미로운 점은, 그 정의가 얼마나 안정적인지, 당신이 제안한대로 관례 적으로 사용되도록 의도되었거나 깨질 가능성이 있습니까?
Manuel

@slim 실제로, 문서는 "이 패키지의 인터페이스는 JDK에서 사용하는 범용 기능 인터페이스이며 사용자 코드에서도 사용할 수 있습니다."라고 대답합니다.
Manuel

14

Java 7 이하에서는 아직 유효하지 않지만 미래를 바라보고 최소한 변경 사항을 인식해야한다고 생각합니다 Java 8과 같은 새로운 버전에서 을 .

즉,이 새 버전은 새로운 API 와 함께 Java에 대한 람다 및 메소드 참조를 제공합니다. 함께이 문제에 대한 또 다른 유효한 솔루션입니다. 여전히 인터페이스가 필요하지만 새 오브젝트가 작성되지 않고 추가 클래스 파일이 다른 이유로 인해 출력 디렉토리를 오염시킬 필요가 없습니다. JVM에 의한 처리.

두 특징 (람다 및 메소드 참조)에는 서명이 사용되는 단일 메소드로 사용 가능한 인터페이스가 필요합니다.

public interface NewVersionTest{
    String returnAString(Object oIn, String str);
}

방법의 이름은 여기서부터 중요하지 않습니다. 람다가 허용되는 경우 메소드 참조도 가능합니다. 예를 들어 여기에서 서명을 사용하려면

public static void printOutput(NewVersionTest t, Object o, String s){
    System.out.println(t.returnAString(o, s));
}

이것은 람다 1 이 전달 될 때까지 간단한 인터페이스 호출입니다 .

public static void main(String[] args){
    printOutput( (Object oIn, String sIn) -> {
        System.out.println("Lambda reached!");
        return "lambda return";
    }
    );
}

출력됩니다 :

Lambda reached!
lambda return

메소드 참조는 유사합니다. 주어진:

public class HelperClass{
    public static String testOtherSig(Object o, String s){
        return "real static method";
    }
}

그리고 주요 :

public static void main(String[] args){
    printOutput(HelperClass::testOtherSig);
}

출력은입니다 real static method. 메소드 참조는 정적, 인스턴스, 임의 인스턴스가있는 비 정적 및 생성자 일 수 있습니다. 생성자에는 비슷한 ClassName::new것이 사용됩니다.

1 부작용이 있기 때문에 일부에서는 람다로 간주되지 않습니다. 그러나보다 직관적 인 방식으로 사용하는 방법을 보여줍니다.


12

마지막으로 확인했을 때 Java는 원하는 것을 기본적으로 수행 할 수 없습니다. 이러한 한계를 극복하려면 '해결 방법'을 사용해야합니다. 내가 아는 한 인터페이스는 대안이지만 좋은 대안은 아닙니다. 아마도 당신에게 말한 사람은 다음과 같은 의미 일 것입니다.

public interface ComponentMethod {
  public abstract void PerfromMethod(Container c);
}

public class ChangeColor implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public class ChangeSize implements ComponentMethod {
  @Override
  public void PerfromMethod(Container c) {
    // do color change stuff
  }
}

public void setAllComponents(Component[] myComponentArray, ComponentMethod myMethod) {
    for (Component leaf : myComponentArray) {
        if (leaf instanceof Container) { //recursive call if Container
            Container node = (Container) leaf;
            setAllComponents(node.getComponents(), myMethod);
        } //end if node
        myMethod.PerfromMethod(leaf);
    } //end looping through components
}

그런 다음 호출 할 내용 :

setAllComponents(this.getComponents(), new ChangeColor());
setAllComponents(this.getComponents(), new ChangeSize());

6

무언가를 반환하기 위해 이러한 메소드가 필요하지 않으면 Runnable 객체를 반환하도록 할 수 있습니다.

private Runnable methodName (final int arg) {
    return (new Runnable() {
        public void run() {
          // do stuff with arg
        }
    });
}

그런 다음 다음과 같이 사용하십시오.

private void otherMethodName (Runnable arg){
    arg.run();
}

2

java.util.function.Function간단한 메소드를 매개 변수 함수로 사용하는 방법에 대한 명확한 예를 찾지 못했습니다 . 다음은 간단한 예입니다.

import java.util.function.Function;

public class Foo {

  private Foo(String parameter) {
    System.out.println("I'm a Foo " + parameter);
  }

  public static Foo method(final String parameter) {
    return new Foo(parameter);
  }

  private static Function parametrisedMethod(Function<String, Foo> function) {
    return function;
  }

  public static void main(String[] args) {
    parametrisedMethod(Foo::method).apply("from a method");
  }
}

기본적으로 Foo기본 생성자 가있는 객체가 있습니다. method로부터 매개 변수로 호출됩니다 parametrisedMethod타입이다 Function<String, Foo>.

  • Function<String, Foo>함수가 String매개 변수로 매개 변수를 사용하고 a 를 반환 한다는 것을 의미합니다 Foo.
  • Foo::Method같은 람다 대응x -> Foo.method(x);
  • parametrisedMethod(Foo::method) 로 볼 수 있었다 x -> parametrisedMethod(Foo.method(x))
  • .apply("from a method")할 기본적으로parametrisedMethod(Foo.method("from a method"))

그러면 출력으로 돌아갑니다.

>> I'm a Foo from a method

예제는있는 그대로 실행해야하며, 다른 클래스와 인터페이스를 사용하여 위의 답변에서 더 복잡한 작업을 시도 할 수 있습니다.


(가)에 전화를 적용 안드로이드는 최소 API를 24 필요한 사용하기
아이 네스 Belhouchet

1

Java에는 이름을 전달하고 호출하는 메커니즘이 있습니다. 반사 메커니즘의 일부입니다. 함수는 Method 클래스의 추가 매개 변수를 가져야합니다.

public void YouMethod(..... Method methodToCall, Object objWithAllMethodsToBeCalled)
{
...
Object retobj = methodToCall.invoke(objWithAllMethodsToBeCalled, arglist);
...
}

1

나는 자바 전문가는 아니지만 다음과 같이 문제를 해결합니다.

@FunctionalInterface
public interface AutoCompleteCallable<T> {
  String call(T model) throws Exception;
}

내 특수 인터페이스에서 매개 변수를 정의합니다

public <T> void initialize(List<T> entries, AutoCompleteCallable getSearchText) {.......
//call here
String value = getSearchText.call(item);
...
}

마지막으로, initialize 메소드 를 호출하는 동안 getSearchText 메소드를 구현 합니다.

initialize(getMessageContactModelList(), new AutoCompleteCallable() {
          @Override
          public String call(Object model) throws Exception {
            return "custom string" + ((xxxModel)model.getTitle());
          }
        })

실제로 가장 좋은 대답이며 올바른 방법입니다. 더 많은 +1
amdev

0

관찰자 패턴을 사용하십시오 (때로는 리스너 패턴이라고도 함).

interface ComponentDelegate {
    void doSomething(Component component);
}

public void setAllComponents(Component[] myComponentArray, ComponentDelegate delegate) {
    // ...
    delegate.doSomething(leaf);
}

setAllComponents(this.getComponents(), new ComponentDelegate() {
                                            void doSomething(Component component) {
                                                changeColor(component); // or do directly what you want
                                            }
                                       });

new ComponentDelegate()... 인터페이스를 구현하는 익명 형식을 선언합니다.


8
찾고있는 패턴이 아닙니다.
피트 Kirkham

1
관찰자 패턴은 변화에 대응하는 능력을 추상화하는 것입니다. OP는 컬렉션을 반복하는 코드 (방문자 패턴)에서 컬렉션의 각 항목에 대해 수행 된 작업을 추상화하려고합니다.
피트 Kirkham

관찰자 / 리스너 패턴은 ​​실제로 해당 명령 패턴과 동일합니다. 그들은 의도가 다릅니다. 관찰자는 알림에 관한 것이고 명령은 일류 함수 / 람다를 대체합니다. 반면에 방문객은 완전히 다른 것입니다. 나는 그것이 두 문장으로 설명 될 수 있다고 생각하지 않으므로 en.wikipedia.org/wiki/Visitor_pattern
EricSchaefer

0

기본 예는 다음과 같습니다.

public class TestMethodPassing
{
    private static void println()
    {
        System.out.println("Do println");
    }

    private static void print()
    {
        System.out.print("Do print");
    }

    private static void performTask(BasicFunctionalInterface functionalInterface)
    {
        functionalInterface.performTask();
    }

    @FunctionalInterface
    interface BasicFunctionalInterface
    {
        void performTask();
    }

    public static void main(String[] arguments)
    {
        performTask(TestMethodPassing::println);
        performTask(TestMethodPassing::print);
    }
}

산출:

Do println
Do print

0

여기에 매개 변수가 바인딩 된 메서드를 메서드의 매개 변수로 전달하는 방법을 보여주는 해결책을 찾지 못했습니다. Bellow는 매개 변수 값이 이미 바인딩 된 메소드를 전달하는 방법의 예입니다.

  1. 1 단계 : 리턴 유형이있는 인터페이스 하나와없는 인터페이스를 두 개 작성하십시오. Java는 비슷한 인터페이스를 가지고 있지만 예외 발생을 지원하지 않기 때문에 실용성이 거의 없습니다.


    public interface Do {
    void run() throws Exception;
    }


    public interface Return {
        R run() throws Exception;
    }
  1. 트랜잭션에서 메소드 호출을 랩핑하기 위해 두 인터페이스를 사용하는 방법의 예. 실제 매개 변수와 함께 메소드를 전달합니다.


    //example - when passed method does not return any value
    public void tx(final Do func) throws Exception {
        connectionScope.beginTransaction();
        try {
            func.run();
            connectionScope.commit();
        } catch (Exception e) {
            connectionScope.rollback();
            throw e;
        } finally {
            connectionScope.close();
        }
    }

    //Invoke code above by 
    tx(() -> api.delete(6));

또 다른 예는 실제로 무언가를 반환하는 메소드를 전달하는 방법을 보여줍니다.



        public  R tx(final Return func) throws Exception {
    R r=null;
    connectionScope.beginTransaction();
    try {
                r=func.run();
                connectionScope.commit();
            } catch (Exception e) {
                connectionScope.rollback();
                throw e;
            } finally {
                connectionScope.close();
            }
        return r;
        }
        //Invoke code above by 
        Object x= tx(() -> api.get(id));

0

리플렉션이있는 솔루션의 예, 전달 된 방법은 공용이어야합니다

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

public class Program {
    int i;

    public static void main(String[] args) {
        Program   obj = new Program();    //some object

        try {
            Method method = obj.getClass().getMethod("target");
            repeatMethod( 5, obj, method );
        } 
        catch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            System.out.println( e ); 
        }
    }

    static void repeatMethod (int times, Object object, Method method)
        throws IllegalAccessException, InvocationTargetException {

        for (int i=0; i<times; i++)
            method.invoke(object);
    }
    public void target() {                 //public is necessary
        System.out.println("target(): "+ ++i);
    }
}

0

위의 답변에 감사하지만 아래 방법을 사용하여 동일한 동작을 수행 할 수있었습니다. Javascript 콜백에서 빌린 아이디어. 나는 지금까지 (생산 중) 잘 교정 할 수 있습니다.

아이디어는 서명에 함수의 반환 유형을 사용하는 것입니다. 즉, 수율이 정체되어야합니다.

다음은 시간 초과로 프로세스를 실행하는 함수입니다.

public static void timeoutFunction(String fnReturnVal) {

    Object p = null; // whatever object you need here

    String threadSleeptime = null;

    Config config;

    try {
        config = ConfigReader.getConfigProperties();
        threadSleeptime = config.getThreadSleepTime();

    } catch (Exception e) {
        log.error(e);
        log.error("");
        log.error("Defaulting thread sleep time to 105000 miliseconds.");
        log.error("");
        threadSleeptime = "100000";
    }

    ExecutorService executor = Executors.newCachedThreadPool();
    Callable<Object> task = new Callable<Object>() {
        public Object call() {
            // Do job here using --- fnReturnVal --- and return appropriate value
            return null;
        }
    };
    Future<Object> future = executor.submit(task);

    try {
        p = future.get(Integer.parseInt(threadSleeptime), TimeUnit.MILLISECONDS);
    } catch (Exception e) {
        log.error(e + ". The function timed out after [" + threadSleeptime
                + "] miliseconds before a response was received.");
    } finally {
        // if task has started then don't stop it
        future.cancel(false);
    }
}

private static String returnString() {
    return "hello";
}

public static void main(String[] args) {
    timeoutFunction(returnString());
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.