2013-08-15 40 views
6

Sự cố này xuất phát từ việc nhập hàm tạo của javax.validation.ConstraintViolationException. Nó chấp nhận Set<ConstraintViolation<?>> làm đối số.Không thể nhập khi đối số chấp nhận Bộ sưu tập <X<?>>

Trong khi rất dễ dàng để có được một tập hợp các ConstraintViolation < X> trong đó X là một loại cụ thể, có vẻ như không thể có được một tập hợp "ConstraintViolation <?>" Từ bất kỳ API được đánh máy nào. Và không thể chuyển đổi cái cũ sang cái sau mà không sử dụng một số phôi phức tạp. (Truyền tới Set<? extends ConstraintViolation<?>> và sau đó đến Set<ConstraintViolation<?>>.)

Vì vậy, các bạn có nghĩ rằng API sai hoặc tôi sai (và tại sao)?

+3

Tại sao bạn cho rằng không thể có được 'Đặt >'? Bạn có thể cho thấy một số ví dụ cụ thể, nơi bạn thấy mình bị mắc kẹt trong vấn đề này? –

+0

Có vẻ như nhà xây dựng đó nên dùng 'Set > 'thay thế. –

+2

Tôi nghĩ rằng đó là một bản sao của http://stackoverflow.com/questions/12096846/how-do-i-construct-a-constraintviolationexception – Katona

Trả lời

4

API sai. Trừ khi triển khai cần thêm ConstraintViolation<?> s mới vào bộ này, nó phải chấp nhận tất cả Set<? extends ConstraintViolation<?>>.

Dưới đây là một ví dụ chứng minh tại sao điều này là linh hoạt hơn (được cung cấp bởi Paul Bellora, nhờ):

public class Main { 

    interface Foo<T> { } 

    interface SubFoo<T> extends Foo<T> { } 

    static class Bar { } 

    public static void main(String[] args) { 

     Set<Foo<?>> arg1 = null; 
     Set<SubFoo<?>> arg2 = null; 
     Set<Foo<Bar>> arg3 = null; 
     Set<SubFoo<Bar>> arg4 = null; 

     Set<Foo<?>> inflexibleParam; 
     inflexibleParam = arg1; //success 
     inflexibleParam = arg2; //incompatible types 
     inflexibleParam = arg3; //incompatible types 
     inflexibleParam = arg4; //incompatible types 

     Set<? extends Foo<?>> flexibleParam; 
     flexibleParam = arg1; //success 
     flexibleParam = arg2; //success 
     flexibleParam = arg3; //success 
     flexibleParam = arg4; //success 
    } 
} 

(ideone)

+1

Huh? http://ideone.com/5xeuqp –

+0

@OliCharlesworth Tôi nghĩ rằng bạn có thể đã hiểu sai câu trả lời. –

+0

Tôi đoán bạn có thể chuyển bất kỳ loại tham số nào vào 'ConstraintViolation '. –

2

API là sai.

Lý tưởng nhất là bất kỳ nơi nào chúng tôi muốn chấp nhận loại chung chung phù hợp, chúng tôi nên sử dụng ? extends.

Một số khai báo chung chung là biến thể vốn có, có nghĩa là chúng phải luôn được sử dụng với ký tự đại diện, ví dụ: Iterator. Nếu một Iterator được sử dụng mà không có ký tự đại diện, nó gần như chắc chắn sai.

Vấn đề là, cú pháp ký tự đại diện quá chi tiết, mọi người bị tắt và thường quên sử dụng nó. Điều này được lan truyền rộng rãi ngay cả trong libs cốt lõi, ví dụ: Iterable<T>.iterator() trả về Iterator<T>, trong khi trả lại Iterator<? extends T>.

Xóa, trớ trêu thay, có thể giải quyết vấn đề này. Chúng tôi biết một Iterator<Apple> có thể được sử dụng an toàn như Iterator<Fruit> tĩnh và chúng tôi biết rằng chúng tôi có thể nhanh chóng truyền Iterator<Apple> đến Iterator<Fruit> động, nhờ xóa. Vì vậy, chỉ cần đi trước và làm diễn viên brute.

+0

+1 Nhưng lưu ý rằng nó thường không hữu ích đối với * trả về * các kiểu generic với '? extends' mặc dù - các tham số phương thức là nơi chúng có thể thêm tính linh hoạt. –

+0

Sẽ hữu ích khi triển khai phân lớp để trả lại một 'Iterator ' làm một 'Iterator '. – ZhongYu

+0

Tại sao? Điều đó không chỉ đơn giản là xóa thông tin? –

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