2011-12-26 28 views
9

Đây là loại một theo dõi câu hỏi về cuộc thảo luận:Java 7 kim cương hoạt động trong lời gọi phương thức

Why doesn't the diamond operator work within a addAll() call in Java 7?

Từ Hướng dẫn Java,

http://docs.oracle.com/javase/tutorial/java/generics/gentypeinference.html

Lưu ý rằng kim cương thường hoạt động trong các cuộc gọi phương thức; tuy nhiên, để rõ ràng hơn, bạn nên sử dụng kim cương chủ yếu để khởi tạo biến mà nó được khai báo là

Vì vậy, tôi hơi bối rối về dòng đầu tiên. Khi hiện hoạt động của kim cương trong các cuộc gọi phương thức?

Giải thích một chút về cách hoạt động của nhà điều hành kim cương tại đây:

http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#What%20is%20type%20argument%20inference%20for%20constructors?

Và từ đó, tôi đã cố gắng điều sau đây, trong đó hoạt động tốt:

Cho rằng tôi có:

private static class Box<T>{ 
    public Box(T t){} 
} 
static void f(Box<Integer> box){} 

một cuộc gọi như sau biên dịch tốt:

f(new Box<>(new Integer(10))); 

Các tham số kiểu trong việc gọi hàm tạo trong lời gọi phương thức của f() ở trên được suy ra từ đối số cho hàm tạo (tức là Integer).

Vì vậy, là thế này có nghĩa là gì khi các hướng dẫn nói

Lưu ý rằng kim cương thường làm việc trong phương pháp gọi

Nếu không, bất cứ ai loại, đủ có thể cung cấp một ví dụ nơi kim cương công trình trong cuộc gọi phương thức?

+0

@gurung một lỗi đánh máy. Trường hợp bị cắt và dán không hợp lệ: ( –

Trả lời

3

Vì vậy, là thế này có nghĩa là gì khi các hướng dẫn nói

Tôi nghĩ có mặc dù có một vài gotchas khi nói đến <> nhà khai thác.

Trong trường hợp của bạn, việc khởi tạo hộp là một vấn đề không phải do loại có thể được phỏng đoán nhỏ bằng cách sử dụng đối số hàm tạo. Hãy thử thay đổi hàm tạo thành "không" có trong một số Integer hoặc T và xem cách gọi không thành công.

class BadBox<T> { 

    private T t; 

    public BadBox(){}  

    public void setT(T t) { 
     this.t = t; 
    } 

    static void f(BadBox<Integer> box){} 

    public static void main(final String[] args) { 
     f(new BadBox<>()); //fails, should have worked ideally 
    }  
} 

Tương tự như vậy, có một cái nhìn tại lớp này:

class Testi<R> {  
    public void doIt(Set<? extends R> sets) { 
    } 

    public static void main(final String[] args) { 
      // works since type inference is now possible 
     new Testi<CharSequence>().doIt(new HashSet<>(Arrays.asList("a"))); 

      // fails; nothing which can help with type inference 
     new Testi<CharSequence>().doIt(new HashSet<>(); 
    }  
} 

Tương tự như vậy, vấn đề trong câu hỏi liên kết của bạn (liên quan đến addAll) có thể được chỉ đơn giản là giải quyết bằng cách giúp đỡ các trình biên dịch một chút như sau:

List<String> list = new ArrayList<>(); 
list.add("A"); 

// works now! use only if you love diamond operator ;) 
list.addAll(new ArrayList<>(Arrays.asList(new String[0]))); 
// or the old-school way 
list.addAll(new ArrayList<String>())); 

Các nhà khai thác kim cương dường như sẽ phá vỡ khi thực hiện các lớp ẩn danh như sau:

final String[] strings = { "a", "b", "c" }; 
Arrays.sort(strings, new Comparator<>() { 
    @Override 
    public int compare(String o1, String o2) { 
     return 0; 
    } 
}); 

May mắn thay, trong trường hợp này, trình biên dịch khá rõ ràng khi đề cập rằng <> không/sẽ không hoạt động với các lớp ẩn danh.

+1

câu trả lời tốt +1. –

0

Nó không thực sự về lời gọi phương thức. Câu lệnh độc lập

new Box<>(new Integer(10)); 

cũng biên dịch. Có đủ thông tin để suy ra T cho Box (ví dụ: từ lập luận Integer)

Mặt khác, điều này không biên dịch

new ArrayList<>(); 

Không có cách nào để biết những gì loại danh sách được mong muốn.

Collection<String> strings = new ArrayList<>(); 

này hoạt động vì suy luận được sự giúp đỡ của các loại mục tiêu Collection<String>

+1

'new ArrayList <>();' như một câu lệnh độc lập * làm * biên dịch. – Holger

1

Tôi không nghĩ rằng nó là đáng suy nghĩ về khi nó hoạt động và khi không. Trình biên dịch sẽ cho bạn biết và do đó bạn phải viết lại những gì không hoạt động.

Không có lý do thực sự đằng sau nó; nó giống như các nhà phát triển đã đặt những hạn chế hiện tại của việc thực hiện trình biên dịch thực tế tại một thời điểm cụ thể vào đặc điểm kỹ thuật và nói với chúng tôi: đó là cách thực hiện.

Java 8 nâng cấp rất nhiều những hạn chế này mà không bị đóng băng. Ví dụ.

Arrays.asList("foo", "bar").addAll(new ArrayList<>()); 

biên dịch với Java 8 mà không có bất kỳ lỗi nào. Và tại sao không?

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