2013-07-11 40 views
11

Tôi muốn hỏi về các quy tắc xóa loại java.Java Generics type erasure

Nếu chúng ta có các lớp học:

public class Shape{} 
public class Circle extends Shape{} 


public class Base<T extends Shape>{ 
    T x; 
    public void setX(T t){} 
} 

public class MainClass(){ 
    public static void main(String... _arg){ 
     Base<? extends Shape> bs = new Base<Circle>(); 
     bs.setX(new Circle()); // <- compilation problem 
    } 
} 

bạn có thể vui lòng giải thích cho tôi tại sao gọi setX() phương pháp gây ra vấn đề biên soạn?

+1

'? super Shape' sẽ hoạt động ở đó. "Nhà sản xuất mở rộng, Siêu tiêu dùng" –

+0

@MichaelMyers: Au contraire: http://ideone.com/TYr10C. 'Base 'chấp nhận một' Base' của bất kỳ * supertype * nào của 'Shape'. –

Trả lời

21

Bởi vì trình biên dịch không biết rằng new Circle là hợp lệ. Hãy xem xét đoạn mã này: "Nhưng các trình biên dịch có thể nhìn thấy nó thực sự là một Base<Square>"

Base<? extends Shape> bs = new Base<Square>(); // Really a Base<Square> 
bs.setX(new Circle()); 

(. FYI, một ví dụ rất tương tự được đưa ra trong Java tutorial on wildcards)

Bây giờ bạn có thể kêu lên. Nhưng không phải nói chung. Hãy xem xét điều này:

Base<? extends Shape> bs = someInterface.getBaseOfSomeKindOfShape(); 
bs.setX(new Circle()); 
+6

+1 Hoặc '(Math.random()> .5)? cơ sở mới (): cơ sở mới () '. Không có cách nào trình biên dịch có thể hình dung ra điều đó. – arshajii

+0

Hiện đã rõ. Cảm ơn ! :) –