generics trên phương pháp không liên quan đến các lớp thông số chung
bạn cần phải lặp lại chúng trên phương pháp cho nó là đúng, ví dụ
Callback<Boolean> callback = new Callback<Boolean>() {
@Override
public <X,Y> Boolean execute(Operation<X, Y> operation) {
}
};
executor.execute(callback);
Nói cách khác, giao diện yêu cầu phương thức thực thi hoạt động trên mọi thông số Hoạt động.
Nếu bạn muốn gọi lại chỉ hoạt động trên các thông số cụ thể bạn cần phải đặt chúng thành một phần của chữ ký lớp, ví dụ:
public interface Callback<T,K,V> {
T execute(Operation<K, V> operation) throws SomeException;
}
mà sau đó sẽ cho phép bạn làm
Callback<Boolean,String,String> callback = new Callback<Boolean,String,String>() {
@Override
public Boolean execute(Operation<String, String> operation) {
}
};
executor.execute(callback);
Tôi không thể nhìn thấy một con đường để nhận được những gì bạn muốn ... trừ khi bạn bắt đầu sử dụng <? super K,? super V>
hoặc <? extends K,? extends V>
hình thức mà có thể hạn chế bạn quá nhiều.
Đây là những gì giao diện của bạn xóa để
public interface Callback<T> {
T execute(Operation<Object, Object> operation) throws SomeException;
}
sau đó khi bạn khởi tạo với T == Boolean
chúng tôi nhận
public interface Callback {
Boolean execute(Operation<Object, Object> operation) throws SomeException;
}
mà không thể được thực hiện bởi một phương pháp
Boolean execute(Operation<String, String> operation) throws SomeException;
như trong thông số hẹp hơn. Bạn có thể mở rộng trong các tham số và thu hẹp các tham số nhưng bạn không thể đi theo cách khác.
Điều đó giải thích tại sao bạn có thể thay đổi kiểu trả về (trong tham số) Object
-Boolean
như bất cứ ai mong đợi một Object
sẽ được hạnh phúc với một Boolean
.
Ngược lại, chúng tôi không thể mở rộng loại trả lại vì điều này sẽ cung cấp cho một ClassCastException
cho bất kỳ ai gọi phương thức và hành động trên kết quả.
Đối số phương pháp (trong tham số) chỉ có thể được mở rộng. Bây giờ nó là hơi phức tạp cho các đối số phương pháp như Java thấy loại khác nhau như các phương pháp khác nhau, vì vậy bạn một cách hợp pháp có thể có
public interface Callback<T> {
T execute(Object key, Object value);
}
Callback<Boolean> cb = new Callback<Boolean> {
@Override
public Boolean execute(Object k, Object v) { ... }
// not an @Override
public Boolean execute(String k, String v) { ... }
}
vì phương pháp thứ hai có chữ ký khác nhau.Nhưng lớp học Operation<X,Y>
của bạn sẽ bị xóa chỉ thành loại thô bất kể đó có phải là số Operation<String,String>
hoặc Operation<X,Y>
Có một điều bạn có thể làm ... nhưng nó trở nên lộn xộn!
public interface StringOperation extends Operation<String,String> {}
sau đó bạn có thể làm
Callback<Boolean> cb = new Callback<Boolean> {
@Override
public <K,V> Boolean execute(Operation<K,V> o) { ... }
// not an @Override
public Boolean execute(StringOperation o) { ... }
}
nhưng hãy nhớ rằng phương pháp execute(Callback<?>)
sẽ gọi <K,V> Boolean execute(Operation<K,V> o)
và không Boolean execute(StringOperation o)
lỗi biên dịch gì bạn nhận được? Tôi có thể thấy rằng hàm của bạn không có câu lệnh trả về, đó là lỗi biên dịch. –
lý do lỗi biên dịch là gì? Và 'SomeException' ở đâu? – mishadoff
Tôi khuyên bạn không nên sử dụng lại tên của bất kỳ lớp học hoặc giao diện phổ biến nào và sử dụng tên khác thay thế. Việc sử dụng lại tên sẽ dẫn đến sự nhầm lẫn như bạn có. –