Phương thức Java Pass làm tham số


277

Tôi đang tìm cách để vượt qua một phương pháp bằng cách tham khảo. Tôi hiểu rằng Java không truyền các phương thức làm tham số, tuy nhiên, tôi muốn có một phương án.

Tôi đã được bảo rằng các giao diện là phương thức thay thế cho việc truyền các phương thức dưới dạng tham số nhưng tôi không hiểu làm thế nào một giao diện có thể hoạt động như một phương thức bằng cách tham chiếu. Nếu tôi hiểu chính xác một giao diện chỉ đơn giản là một tập hợp các phương thức không được xác định. Tôi không muốn gửi một giao diện cần được xác định mỗi lần vì một số phương thức khác nhau có thể gọi cùng một phương thức với cùng tham số.

Những gì tôi muốn thực hiện là một cái gì đó tương tự như thế này:

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
}

được gọi như:

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

ngay bây giờ giải pháp của tôi là truyền một tham số bổ sung và sử dụng hộp chuyển đổi bên trong để chọn phương thức thích hợp. Tuy nhiên, giải pháp này không cho vay trong khi sử dụng lại mã.

Xem thêm câu trả lời này stackoverflow.com/a/22933032/1010868 cho câu hỏi tương tự
Tomasz Gawel

Câu trả lời:


233

Chỉnh sửa : kể từ Java 8, các biểu thức lambda là một giải pháp hay như các câu trả lời khác đã chỉ ra. Câu trả lời dưới đây được viết cho Java 7 và trước đó ...


Hãy nhìn vào mẫu lệnh .

// 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");
    }
}

Chỉnh sửa: như Pete Kirkham chỉ ra , có một cách khác để thực hiện việc này bằng cách sử dụng Khách truy cập . Cách tiếp cận khách truy cập có liên quan nhiều hơn một chút - tất cả các nút của bạn cần phải nhận biết khách truy cập bằng một acceptVisitor()phương thức - nhưng nếu bạn cần duyệt qua một biểu đồ đối tượng phức tạp hơn thì nó đáng để kiểm tra.


2
@Mac - tốt! cái này xuất hiện lặp đi lặp lại trong các ngôn ngữ mà không có phương pháp hạng nhất như là cách mô phỏng thực tế, vì vậy nó đáng để ghi nhớ.
Dan Vinton

7
Đó là mẫu khách truy cập (tách hành động lặp lại một bộ sưu tập khỏi hàm được áp dụng cho từng thành viên của bộ sưu tập), chứ không phải mẫu lệnh (gói gọn các đối số cho một cuộc gọi phương thức vào một đối tượng). Bạn đặc biệt không gói gọn đối số - nó được cung cấp bởi phần lặp của mẫu khách truy cập.
Pete Kirkham

Không, bạn chỉ cần phương thức chấp nhận nếu bạn kết hợp truy cập với công văn kép. Nếu bạn có một khách truy cập đơn hình, đó chính xác là mã bạn có ở trên.
Pete Kirkham

Trong Java 8 có thể giống như ex.operS (String :: toLowerCase, "STRING"). Xem bài viết hay: learntrails.com/java/java8/ Google
Zon

Pete Kirkham đã đúng: mã của bạn đang triển khai mẫu Khách truy cập, không phải mẫu Lệnh (và điều này tốt, vì đó là những gì OP cần.) Như Pete nói, bạn không gói gọn đối số, vì vậy bạn không thực hiện Lệnh - Lệnh của bạn giao diện có một thực thi có một tham số. Wikipedia thì không. Điều này là cơ bản cho ý định của mẫu Lệnh. Như đoạn đầu tiên nói "đóng gói tất cả thông tin ... Thông tin này bao gồm tên phương thức, đối tượng sở hữu phương thức và giá trị cho các tham số phương thức ."
ToolmakerSteve

73

Trong Java 8, giờ đây bạn có thể chuyển một phương thức dễ dàng hơn bằng cách sử dụng Biểu thức và tham chiếu phương thức Lambda . Đầu tiên, một số nền tảng: giao diện chức năng là một giao diện có một và chỉ một phương thức trừu tượng, mặc dù nó có thể chứa bất kỳ số phương thức mặc định nào (mới trong Java 8) và các phương thức tĩnh. Biểu thức lambda có thể nhanh chóng thực hiện phương thức trừu tượng mà không cần tất cả các cú pháp không cần thiết nếu bạn không sử dụng biểu thức lambda.

Không có biểu thức lambda:

obj.aMethod(new AFunctionalInterface() {
    @Override
    public boolean anotherMethod(int i)
    {
        return i == 982
    }
});

Với biểu thức lambda:

obj.aMethod(i -> i == 982);

Đây là một đoạn trích từ hướng dẫn Java về Lambda Expressions :

Cú pháp của biểu thức Lambda

Một biểu thức lambda bao gồm:

  • Một danh sách các tham số chính thức được phân tách bằng dấu phẩy được đặt trong dấu ngoặc đơn. Phương thức CheckPerson.test chứa một tham số, p, đại diện cho một thể hiện của lớp Person.

    Lưu ý : Bạn có thể bỏ qua kiểu dữ liệu của các tham số trong biểu thức lambda. Ngoài ra, bạn có thể bỏ qua dấu ngoặc đơn nếu chỉ có một tham số. Ví dụ: biểu thức lambda sau đây cũng hợp lệ:

    p -> p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25
  • Mã thông báo mũi tên, ->

  • Một cơ thể, bao gồm một biểu thức hoặc một khối câu lệnh. Ví dụ này sử dụng biểu thức sau:

    p.getGender() == Person.Sex.MALE 
        && p.getAge() >= 18
        && p.getAge() <= 25

    Nếu bạn chỉ định một biểu thức, thì bộ thực thi Java sẽ đánh giá biểu thức và sau đó trả về giá trị của nó. Ngoài ra, bạn có thể sử dụng câu lệnh return:

    p -> {
        return p.getGender() == Person.Sex.MALE
            && p.getAge() >= 18
            && p.getAge() <= 25;
    }

    Một tuyên bố trở lại không phải là một biểu thức; trong biểu thức lambda, bạn phải đặt các câu lệnh trong dấu ngoặc nhọn ({}). Tuy nhiên, bạn không phải gửi kèm một lời gọi phương thức void trong dấu ngoặc nhọn. Ví dụ: dưới đây là biểu thức lambda hợp lệ:

    email -> System.out.println(email)

Lưu ý rằng biểu thức lambda trông rất giống khai báo phương thức; bạn có thể coi biểu thức lambda là phương thức ẩn danh Phương thức mà không có tên.


Đây là cách bạn có thể "truyền một phương thức" bằng cách sử dụng biểu thức lambda:

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));
    }
}

Lớp Ccó thể được rút ngắn hơn nữa một chút bằng cách sử dụng các tham chiếu phương thức như vậy:

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

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

Có phải lớp A cần được kế thừa từ giao diện?
Serob_b

1
@Serob_b Không. Trừ khi bạn muốn truyền nó dưới dạng tham chiếu phương thức (xem ::toán tử), không quan trọng A là gì. a.changeThing(component)có thể được thay đổi thành bất kỳ câu lệnh hoặc khối mã nào bạn muốn, miễn là nó trả về khoảng trống.
Chàng trai với chiếc mũ

29

Sử dụng java.lang.reflect.Methodđối tượng và gọiinvoke


12
Tôi không thấy lý do tại sao không. Câu hỏi là để vượt qua một phương thức như một tham số và đây là một cách làm rất hợp lệ. Điều này cũng có thể được bọc trong bất kỳ số lượng các mẫu đẹp mắt để làm cho nó trông đẹp. Và điều này là chung chung như nó nhận được mà không cần bất kỳ giao diện đặc biệt.
Vinodh Ramasubramanian

3
Bạn đã gõ an toàn trong JavaScript fg chưa? Loại an toàn không phải là một đối số.
Thủy thủ Danubian

13
Làm thế nào là an toàn loại không phải là một đối số khi ngôn ngữ trong câu hỏi giữ an toàn loại là một trong những thành phần mạnh nhất của nó? Java là một ngôn ngữ được gõ mạnh và việc gõ mạnh là một trong những lý do bạn chọn ngôn ngữ được biên dịch này.
Adam Parkin

21
"Công cụ phản chiếu lõi ban đầu được thiết kế cho các công cụ xây dựng ứng dụng dựa trên thành phần. [...] Theo quy định, các đối tượng không nên được truy cập một cách phản xạ trong các ứng dụng thông thường khi chạy." Mục 53: Thích các giao diện để phản chiếu, từ Ấn bản thứ hai hiệu quả của Java. - Đó là dòng suy nghĩ của những người tạo ra Java ;-)
Wilhem Meignan

8
Không sử dụng chính đáng của phản ánh. Tôi kinh hoàng khi thấy tất cả các upvote. phản ánh không bao giờ có ý định được sử dụng như một cơ chế lập trình chung; Chỉ sử dụng nó khi không có giải pháp sạch khác.
ToolmakerSteve

22

Vì Java 8 có một Function<T, R>giao diện ( docs ), có phương thức

R apply(T t);

Bạn có thể sử dụng nó để truyền các hàm làm tham số cho các hàm khác. T là kiểu đầu vào của hàm, R là kiểu trả về.

Trong ví dụ của bạn, bạn cần truyền một hàm lấy Componentkiểu làm đầu vào và không trả về gì - Void. Trong trường hợp Function<T, R>này không phải là sự lựa chọn tốt nhất, vì không có hộp số tự động loại Void. Giao diện bạn đang tìm kiếm được gọi là Consumer<T>( docs ) với phương thức

void accept(T t);

Nó sẽ trông như thế này:

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);
    } 
}

Và bạn sẽ gọi nó bằng cách sử dụng các tham chiếu phương thức:

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

Giả sử rằng bạn đã định nghĩa các phương thức changeColor () và changeSize () trong cùng một lớp.


Nếu phương thức của bạn chấp nhận nhiều hơn một tham số, bạn có thể sử dụng BiFunction<T, U, R>- T và U là các loại tham số đầu vào và R là loại trả về. Ngoài ra còn có BiConsumer<T, U>(hai đối số, không có kiểu trả về). Thật không may cho 3 tham số đầu vào trở lên, bạn phải tự tạo một giao diện. Ví dụ:

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

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

19

Trước tiên, xác định Giao diện với phương thức bạn muốn truyền làm tham số

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

Thực hiện một lớp với phương thức

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

// Gọi như thế

Callable cmd = new Test();

Điều này cho phép bạn truyền cmd làm tham số và gọi cuộc gọi phương thức được xác định trong giao diện

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

1
Bạn có thể không phải tạo giao diện của riêng mình vì java đã xác định rất nhiều giao diện cho bạn: docs.oracle.com/javase/8/docs/api/java/util/feft/ trộm
slim

@slim Điểm thú vị, những định nghĩa đó ổn định đến mức nào, chúng có được sử dụng theo cách thông thường như bạn đề xuất không, hoặc có khả năng phá vỡ không?
Manuel

@slim Trên thực tế, các tài liệu trả lời rằng: "Các giao diện trong gói này là các giao diện chức năng cho mục đích chung được sử dụng bởi JDK và cũng có sẵn để được sử dụng bởi mã người dùng."
Manuel

14

Mặc dù điều này chưa hợp lệ đối với Java 7 trở xuống, tôi tin rằng chúng ta nên nhìn về tương lai và ít nhất là nhận ra những thay đổi sẽ có trong các phiên bản mới như Java 8.

Cụ thể, phiên bản mới này mang đến lambdas và các tham chiếu phương thức cho Java (cùng với các API mới , là một giải pháp hợp lệ khác cho vấn đề này. Mặc dù chúng vẫn yêu cầu giao diện không có đối tượng mới nào được tạo và các tệp lớp bổ sung không cần gây ô nhiễm thư mục đầu ra do khác nhau xử lý bởi JVM.

Cả hai hương vị (lambda và tham chiếu phương thức) đều yêu cầu giao diện có sẵn với một phương thức duy nhất có chữ ký được sử dụng:

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

Tên của các phương thức sẽ không quan trọng từ đây về sau. Trường hợp lambda được chấp nhận, tham chiếu phương thức là tốt. Ví dụ: để sử dụng chữ ký của chúng tôi ở đây:

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

Đây chỉ là một lời mời giao diện đơn giản, cho đến khi lambda 1 được thông qua:

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

Điều này sẽ xuất ra:

Lambda reached!
lambda return

Phương pháp tham khảo là tương tự. Được:

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

và chính:

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

đầu ra sẽ là real static method. Tham chiếu phương thức có thể là tĩnh, thể hiện, không tĩnh với các thể hiện tùy ý và thậm chí là các hàm tạo . Đối với các nhà xây dựng một cái gì đó giống như ClassName::newsẽ được sử dụng.

1 Điều này không được coi là lambda bởi một số người, vì nó có tác dụng phụ. Nó thực sự minh họa, tuy nhiên, việc sử dụng một cách đơn giản hơn để dễ hình dung hơn.


12

Lần trước tôi đã kiểm tra, Java không có khả năng thực hiện những gì bạn muốn; bạn phải sử dụng 'công việc xung quanh' để khắc phục những hạn chế đó. Theo như tôi thấy, giao diện là một sự thay thế, nhưng không phải là một sự thay thế tốt. Có lẽ bất cứ ai nói với bạn điều đó có nghĩa là như thế này:

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
}

Mà sau đó bạn gọi với:

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

6

Nếu bạn không cần các phương thức này để trả về một cái gì đó, bạn có thể làm cho chúng trả về các đối tượng Runnable.

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

Sau đó sử dụng nó như:

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

2

Tôi không tìm thấy bất kỳ ví dụ nào đủ rõ ràng cho tôi về cách sử dụng java.util.function.Functioncho phương thức đơn giản là hàm tham số. Đây là một ví dụ đơn giản:

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");
  }
}

Về cơ bản, bạn có một Foođối tượng với hàm tạo mặc định. Một methodsẽ được gọi là một tham số từ parametrisedMethodđó là loại Function<String, Foo>.

  • Function<String, Foo>có nghĩa là hàm lấy Stringtham số làm và trả về a Foo.
  • Tương Foo::Methodứng với một lambda nhưx -> Foo.method(x);
  • parametrisedMethod(Foo::method) có thể được coi là x -> parametrisedMethod(Foo.method(x))
  • Các .apply("from a method")cơ bản là để làmparametrisedMethod(Foo.method("from a method"))

Mà sau đó sẽ trở lại trong đầu ra:

>> I'm a Foo from a method

Ví dụ nên chạy, bạn có thể thử những thứ phức tạp hơn từ các câu trả lời ở trên với các lớp và giao diện khác nhau.


để sử dụng cuộc gọi áp dụng trong Android, bạn cần tối thiểu 24 giờ
Ines Belhouchet

1

Java có một cơ chế để truyền tên và gọi nó. Nó là một phần của cơ chế phản chiếu. Hàm của bạn sẽ lấy tham số bổ sung của Phương thức lớp.

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

1

Tôi không phải là chuyên gia java nhưng tôi giải quyết vấn đề của bạn như thế này:

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

Tôi xác định tham số trong Giao diện đặc biệt của mình

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

Cuối cùng, tôi triển khai phương thức getSearchText trong khi gọi phương thức khởi tạo .

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

Trên thực tế đó là câu trả lời tốt nhất và cách thích hợp để làm điều đó. Xứng đáng hơn +1
amdev 30/10/19

0

Sử dụng mẫu Observer (đôi khi còn được gọi là mẫu Listener):

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()... tuyên bố một loại ẩn danh thực hiện giao diện.


8
Đây không phải là mô hình bạn đang tìm kiếm.
Pete Kirkham

1
Mẫu quan sát là về trừu tượng hóa khả năng đáp ứng với một sự thay đổi. OP muốn trừu tượng hóa hành động được thực hiện tại mỗi mục trong bộ sưu tập khỏi mã lặp trên bộ sưu tập, đó là mẫu khách truy cập.
Pete Kirkham

Mẫu Observer / Listener thực sự giống với mẫu Command đó. Họ chỉ khác nhau về ý định. Người quan sát là về thông báo trong khi lệnh là một thay thế cho các chức năng hạng nhất / lambdas. Mặt khác, khách truy cập là một cái gì đó hoàn toàn khác nhau. Tôi không nghĩ nó có thể được giải thích trong một vài câu vì vậy hãy xem en.wikipedia.org/wiki/Visitor_potype
EricSchaefer

0

Đây là một ví dụ cơ bản:

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);
    }
}

Đầu ra:

Do println
Do print

0

Tôi không tìm thấy bất kỳ giải pháp nào ở đây chỉ ra cách truyền phương thức với các tham số ràng buộc với nó như là một tham số của phương thức. Bellow là ví dụ về cách bạn có thể truyền một phương thức với các giá trị tham số đã được liên kết với nó.

  1. Bước 1: Tạo hai giao diện một với kiểu trả về, một giao diện khác không có. Java có các giao diện tương tự nhưng chúng ít được sử dụng thực tế vì chúng không hỗ trợ ném ngoại lệ.


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


    public interface Return {
        R run() throws Exception;
    }
  1. Ví dụ về cách chúng tôi sử dụng cả hai giao diện để thực hiện cuộc gọi phương thức trong giao dịch. Lưu ý rằng chúng ta truyền phương thức với các tham số thực tế.


    //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));

Một ví dụ khác cho thấy làm thế nào để vượt qua một phương thức thực sự trả về một cái gì đó



        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

Ví dụ về giải pháp với sự phản ánh, phương thức thông qua phải được công khai

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

Tôi đánh giá cao các câu trả lời ở trên nhưng tôi đã có thể đạt được hành vi tương tự bằng phương pháp bên dưới; một ý tưởng mượn từ cuộc gọi lại Javascript. Tôi sẵn sàng điều chỉnh mặc dù cho đến nay vẫn rất tốt (trong sản xuất).

Ý tưởng là sử dụng kiểu trả về của hàm trong chữ ký, nghĩa là sản lượng phải tĩnh.

Dưới đây là một chức năng chạy một quá trình với thời gian chờ.

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());
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.