2012-05-07 36 views
5

Đây là jdk1.7.0_04.Hành vi suy luận kiểu lạ của Collections.emptyList() và/hoặc các phương thức chung Java?

Tôi đã cố gắng sử dụng Collections.emptyList() hơn new ing lên danh sách trống của riêng tôi trong một điều kiện:

List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList(); 

nhưng nhận được lỗi sau:

error: incompatible types 
     List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.emptyList(); 
              ^
    required: List<String> 
    found: List<CAP#1> 
    where CAP#1 is a fresh type-variable: 
    CAP#1 extends Object from capture of ? extends Object 
1 error 

tôi đã có thể hình dung rằng tôi cần phải thay đổi mọi thứ thành:

List<String> list = (anArray != null) ? Arrays.asList(anArray) : Collections.<String>emptyList(); 

Nhưng là một phần của công việc về vấn đề này tôi gặp phải sự kỳ lạ (với tôi, anyways) tình hình rằng:

List<String> alwaysEmpty = Collections.emptyList(); 

biên dịch tốt, nhưng:

List<String> alwaysEmpty = (List<String>) Collections.emptyList(); 

cung cấp cho các lỗi biên dịch sau:

error: inconvertible types 
     List<String> alwaysEmpty = (List<String>) Collections.emptyList(); 
                    ^
    required: List<String> 
    found: List<Object> 

What the heck ??

Bây giờ tôi có thể hiểu rằng có lẽ vì lý do kỳ lạ nào đó, việc sử dụng toán tử điều kiện bằng cách nào đó chặn hệ thống suy luận kiểu từ việc nhận ra tham số kiểu cho cuộc gọi emptyList() phải là String và do đó cần được chỉ định rõ ràng. Nhưng tại sao chèn một (thừa nhận thừa nhận) đúc những điều lộn xộn lên?

Trả lời

9

But why does inserting a (admittedly redundant) cast mess things up?

vì bản thân biểu thức Collections.emptyList() không phải là mục tiêu của bất kỳ bài tập nào - vì vậy, nên chọn đối số kiểu nào? Tốt hơn hết là chỉ để xác định đối số loại:

// Redundant here, but just as an example 
List<String> alwaysEmpty = Collections.<String>emptyList(); 

Nó hoạt động tương tự cho các nhà điều hành có điều kiện, quá:

public static void main(String[] args) {    
    List<String> list = (args != null) 
     ? Arrays.asList(args) : Collections.<String>emptyList(); 
} 
5

Tôi sẽ chấp nhận câu trả lời Jon, nhưng cũng muốn liệt kê là câu trả lời những gì một người nào đó đã chuyển cho tôi về điều này bên ngoài SO. Nó là một liên kết đến một số bug report gửi cho Sun/Oracle về điều này rất. Người đánh giá lỗi có một lời giải thích hữu ích về những gì đang xảy ra. Một đoạn trích:

The submitter here seems to assume that the type of a conditional expression is the type on the LHS of an assigment (List<String> in this case). This is not true: as stated by the JLS, the type of a conditional expression:

"The type of the conditional expression is the result of applying capture conversion (§5.1.10) to lub(T1, T2) (§15.12.2.7). "

It's important to understand why it's necessary to apply lub. Consider the following example:

class A {} 
class B extends A{} 
class C extends A{} 
class Foo<X> 
Foo<? extends A> l = b ? new Foo<B>() : new Foo<C>() 

In this case we have that LHS is of type Foo<? extends A> while the RHS is of type lub(Foo<B>, Foo<C>) , that is Foo<? extends B&C> .

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