2015-12-28 18 views
6

Tôi có một giao diện java như thế nàyBounded Loại thông số đúc vấn đề

public interface MyInterface<T> { 
    public <V extends T> V get(String key, Bundle bundle); 
} 

xin lưu ý các thông số <V extends T> loại phương pháp.

Sau đó, tôi có một lớp MyFoo implements MyInterface

class MyFoo implements MyInterface<Object> { // Object because can be any type 

    @Override public <V> V get(String key, Bundle bundle) { 
    return new Other(); 
    } 
} 

Vì vậy, khi bây giờ tôi có một lớp học như thế này:

class Bar { 
    public Other other; 

    public Other setOther(Other other); 
} 

Sau đó, tôi muốn đi MyFoo thiết Other trong một trường hợp Bar:

MyFoo foo = new MyFoo(); 
Bar bar = new Bar(); 
bar.other = foo.get(); 

Điều này hoạt động hoàn hảo. Loại có thể được xác định bởi Generics java. Không cần thêm diễn viên.

Tuy nhiên, nếu tôi muốn sử dụng bar.setOther() sau đó loại có thể không được xác định:

MyFoo foo = new MyFoo(); 
Bar bar = new Bar(); 
bar.setOther(foo.get()); // Fails 

Sau đó, tôi nhận được lỗi biên dịch sau:

error: incompatible types: Object cannot be converted to Other

Tôi không hiểu tại sao doesn này không hoạt động cho phương thức bar.setOther(foo.get()) nhưng hoạt động khi truy cập trực tiếp vào trường bar.other = foo.get()

Bất kỳ ý tưởng nào để giải quyết điều đó mà không cần addin g một dàn diễn viên phụ như bar.setOther((Other) foo.get())

Trả lời

3

Trong một nhiệm vụ, trình biên dịch Java biết loại trả về nào sẽ sử dụng cho phương pháp bằng cách xem loại mà nó đang được gán cho. Vì vậy, để trả lời câu hỏi của bạn

Any idea how to solve that without adding an extra cast like bar.setOther((Other) foo.get()) ?

Đây là một cách mà bạn có thể làm điều đó:

Other value = foo.get(); 
bar.setOther(value); 

Có một cách khác, trông tồi tệ hơn nhưng vẫn không có một dàn diễn viên:

bar.setOther(foo.<Other>get()); 

Và lựa chọn thứ ba: chuyển sang Java 8; trong Java 8 bạn chỉ có thể làm bar.setOther(foo.get());.

Đối với Java 7, các quy tắc cho suy luận kiểu này được quy định tại JLS section 15.12.2.8:

If any of the method's type arguments were not inferred from the types of the actual arguments, they are now inferred as follows.

If the method result occurs in a context where it will be subject to assignment conversion (§5.2) to a type S, then [...]

Một kết quả phương pháp là tùy thuộc vào chuyển đổi chuyển nhượng nếu nó được sử dụng trong một biểu thức chuyển nhượng.

  • Otherwise, the unresolved type arguments are inferred by invoking the procedure described in this section under the assumption that the method result was assigned to a variable of type Object .

Nếu đối số loại chưa được giải quyết được sử dụng trong một phương pháp mà kết quả không được sử dụng trong một biểu thức chuyển nhượng, sau đó các đối số kiểu được hiểu là nếu kết quả phương pháp đã được gán cho một biến kiểu Object. Vì vậy, điều này có nghĩa trong trường hợp này là nếu kết quả của phương pháp get() không được gán cho một biến, thì kiểu trả về của phương thức get() được lấy là Object.

+0

Vâng, đó là một loại giải pháp thay thế. Vì vậy, trình biên dịch không thể nhìn vào tham số kiểu của 'setOther()'? Âm thanh lạ ... – sockeqwe

+0

@ dasblinkenlight Tôi sẽ đào phần JLS nhưng tôi đoán nó phải làm với thực tế là một phương pháp có thể bị quá tải cho nhiều loại tham số và JLS không muốn cho phép quá trình lựa chọn quá tải và lựa chọn loại bê tông cho các loại chung ảnh hưởng lẫn nhau. –

+0

phương pháp quá tải ... âm thanh hợp lý – sockeqwe

Các vấn đề liên quan