2012-06-18 25 views
45

Có giao diện trong Java tương tự như giao diện Callable, có thể chấp nhận một đối số cho phương thức cuộc gọi của nó không?Có giao diện tương tự với Callable nhưng có đối số không?

Giống như vậy:

public interface MyCallable<V> { 
    V call(String s) throws Exception; 
} 

Tôi thà tránh tạo ra một loại mới nếu có đã tồn tại một cái gì đó mà tôi có thể sử dụng. Hoặc là có một chiến lược tốt hơn để có nhiều khách hàng thực hiện và cắm vào một thói quen có thể gọi được?

sao chép từ đây http://www.programmingforums.org/thread27905.html

+1

Không, nhưng hãy xem những thứ như http://www.programmingforums.org/thread27905.html. –

Trả lời

31

Kể từ Java 8 có một tập hợp toàn bộ giao diện chức năng giống như trong the java.util.function package. Người bạn yêu cầu cụ thể chỉ đơn giản là Function.

Trước Java 8, không có giao diện được tích hợp sẵn cho mục đích chung, nhưng một số thư viện đã cung cấp nó.

Ví dụ Guavathe Function<F,T> interface với phương pháp T apply(F input). Nó cũng làm cho heavy use of that interface ở một số nơi.

+0

Câu hỏi này cũng xảy ra với đồng nghiệp của tôi tuần trước.Lựa chọn đầu tiên và rõ ràng của chúng tôi là sử dụng chức năng từ ổi. Tuy nhiên chúng tôi nhận thấy rằng phương thức apply() không ném ngoại lệ. Điều này khiến nó không phù hợp với mục đích của chúng tôi. Thật không may, chúng tôi đã phải tạo ra giao diện riêng của chúng tôi cho điều đó. Ít nhất nó đã trở thành một lib toàn công ty, được tái sử dụng. –

+1

@FilipeFedalto: tốt, cả hai ngoại lệ-ném và không ném 'Chức năng' có thể hữu ích. Hầu hết việc sử dụng 'Hàm' trong ổi là đơn giản" chuyển đổi thành b "và" lấy foo từ đối tượng Bar "sử dụng không bao giờ (trong một chương trình sane) ném ngoại lệ đã kiểm tra (NPE và những cái không được chọn là một câu chuyện khác). Đó là (có lẽ) tại sao ổi chức năng 'không ném ngoại lệ. –

+0

Bạn đang cố gắng làm gì với nó? Một giao diện như thế này chỉ hữu ích nếu triển khai nó cho phép bạn làm những việc tốt hơn bạn có thể thực hiện trực tiếp. Điều này không phải lúc nào cũng đúng với 'Chức năng', hãy để một mình những con thú phức tạp hơn. –

1

Câu trả lời không rõ ràng. Nói đúng ra, đó là, "cho cùng một mục đích của Giao diện có thể gọi", không có.

Có các lớp tương tự và tùy thuộc vào những gì bạn muốn, chúng có thể hoặc không thuận tiện. Một trong số đó là SwingWorker. Tuy nhiên, như tên của nó, nó được thiết kế để sử dụng trong khuôn khổ Swing. Nó có thể được sử dụng cho các mục đích khác, nhưng đây sẽ là một sự lựa chọn thiết kế kém.

Lời khuyên tốt nhất của tôi là sử dụng thư viện mở rộng (Jakarta-Commons, Guava, v.v.), tùy thuộc vào thư viện bạn đã sử dụng trong hệ thống của mình.

0

Đối số thông thường không bắt buộc vì phương thức có thể có bất kỳ số đối số nào trong hàm tạo của nó.

final int i = 5; 
final String word = "hello"; 

Future<String> future = service.submit(new Callable<String>() { 
    public String call() { 
     return word + i; 
    } 
}); 

Trong ví dụ này iword đã được sử dụng, nhưng bạn có thể "vượt qua" bất kỳ số lượng các tham số.

+0

Thực ra bạn là đúng, NHƯNG chỉ để Mở rộng, từ nhiều quan điểm tạo ra đối tượng Callable mới mỗi lần có thể được trên không và vô dụng. Ví dụ - sau đó bạn xử lý bộ sưu tập lớn theo từng phần tử, từng cái một, Hoặc khi bạn có một số Thành phần và bạn nên chuyển giao quy trình cho anh ta (để tránh trộn lẫn/lộn xộn logic). – iMysak

+0

@iMysak Để chuyển công việc giữa các chủ đề qua hàng đợi, bạn sẽ tạo một vài đối tượng (ít nhất 3 tôi nghi ngờ) –

+0

thực sự, từ thời điểm này bạn hoàn toàn chính xác :) – iMysak

7

lúc đầu nó nghĩ rằng điều này được thực hiện với một giao diện nhưng sau đó tôi thấy rằng nó nên được thực hiện bằng cách sử dụng một lớp trừu tượng.

tôi đã giải quyết nó theo cách này:


chỉnh sửa: thời gian gần đây tôi chỉ sử dụng này:

public static abstract class callback1<T>{ 
     public abstract void run(T value); 
    } 

    public static abstract class callback2<T,J>{ 
     public abstract void run(T value,J value2); 
    } 

    public static abstract class callback3<T,J,Z>{ 
     public abstract void run(T value,J value2,Z value3); 
    } 


    public static abstract class callbackret1<R,T>{ 
     public abstract R run(T value); 
    } 

    public static abstract class callbackret2<R,T,J>{ 
     public abstract R run(T value,J value2); 
    } 

    public static abstract class callbackret3<R,T,J,Z>{ 
     public abstract R run(T value,J value2,Z value3); 
    } 

CallBack.java

public abstract class CallBack<TRet,TArg> { 
    public abstract TRet call(TArg val); 
} 

xác định phương pháp: Phương pháp

class Sample2 
{ 
    CallBack<Void,String> cb; 
    void callcb(CallBack<Void,String> CB) 
    { 
    cb=CB; //save the callback 
    cb.call("yes!"); // call the callback 
    } 
} 

sử dụng:

sample2.callcb(new CallBack<Void,String>(){ 
     @Override 
     public Void call(String val) { 
      // TODO Auto-generated method stub 
      return null; 
     } 
    }); 

hai đối số mẫu: CallBack2.java

public abstract class CallBack2<TRet,TArg1,TArg2> { 
    public abstract TRet call(TArg1 val1,TArg2 val2); 
} 

lưu ý rằng khi bạn sử dụng kiểu trả về Void bạn phải sử dụng trả về null; do đó, đây là một biến thể để khắc phục điều đó vì thường gọi lại không trả về bất kỳ giá trị nào.

khoảng trống như kiểu trả về: SimpleCallBack.java

public abstract class SimpleCallBack<TArg> { 
    public abstract void call(TArg val); 
} 

khoảng trống như kiểu trả về 2 args: SimpleCallBack2.java

public abstract class SimpleCallBack<TArg1,TArg2> { 
    public abstract void call(TArg1 val1,TArg2 val2); 
} 

giao diện không phải là hữu ích cho việc này.

giao diện cho phép nhiều loại khớp với cùng loại. bằng cách có một bộ chức năng được xác định trước.

lớp trừu tượng cho phép các hàm trống bên trong chúng được hoàn thành sau này. mở rộng hoặc khởi tạo.

+0

Tôi cũng nghĩ rằng lớp trừu tượng 'CallBack' của bạn nên là một giao diện, nếu chỉ cho phép thừa kế nhiều (ví dụ nhanh: có một lớp con mở rộng một trong các lớp của bạn, và là một 'CallBack' cùng một lúc). Điều gì khiến bạn thay đổi ý kiến ​​của mình? –

+0

tôi có một cảm giác thtat bạn có thể đúc trước khi vượt qua nó như là đối số. cũng là lớp trừu tượng có thể thực hiện một giao diện mà bạn có thể đặt làm đối số và không yêu cầu đúc –

+0

Tôi vẫn không thấy lợi thế của việc sử dụng lớp trừu tượng: chúng hữu ích nhất khi được sử dụng để cung cấp các phương thức phải được triển khai trong các lớp con. thực hiện để giảm bớt sự phát triển của các lớp con. Ở đây bạn không có bất kỳ mã nào trong các lớp trừu tượng của bạn, chỉ là các phương thức trừu tượng. Do đó, bạn chỉ có thể sử dụng giao diện thay thế. –

4

Gần đây tôi đã có yêu cầu tương tự. Như những người khác đã giải thích nhiều libs cung cấp phương pháp 'chức năng', nhưng chúng không ném ngoại lệ.

Một ví dụ về cách mà một số dự án đã cung cấp một giải pháp là RxJava thư viện nơi họ sử dụng giao diện như ActionX nơi 'X' là 0 ... N, số lượng các đối số cho các gọi phương pháp . Họ thậm chí có giao diện đa dạng, ActionN.

cách tiếp cận hiện tại của tôi là sử dụng một giao diện chung đơn giản:

public interface Invoke<T,V> {  
    public T call(V data) throws Exception;  
// public T call(V... data) throws Exception;  
} 

Phương pháp thứ hai là một lợi thế trong trường hợp của tôi, nhưng nó thể hiện rằng sợ hãi "Loại an toàn: ô nhiễm đống tiềm năng qua varargs dữ liệu tham số" trong IDE của tôi và đó là một vấn đề khác.

Một cách tiếp cận tôi đang xem xét là sử dụng giao diện hiện có như java.util.concurrent.Callable mà không ném ngoại lệ, và trong trường hợp ngoại lệ quấn thực hiện của tôi trong trường hợp ngoại lệ không được kiểm soát.

0

Tôi vừa gặp sự cố tương tự. bạn có thể bọc bất kỳ phương thức nào để trả về một hàm có thể gọi và thực thi giá trị trả về của nó. tức là

main {  
    Callable<Integer> integerCallable = getIntegerCallable(400); 
    Future<Integer> future = executor.submit(integerCallable); 
} 

private Callable<Integer> getIntegerCallable(int n) { 
    return() -> { 
      try { 
       TimeUnit.SECONDS.sleep(n); 
       return 123; 
      } catch (InterruptedException e) { 
       throw new IllegalStateException("task interrupted", e); 
      } 
     }; 
} 
Các vấn đề liên quan