2010-10-23 31 views
27

Given:Tại sao tôi nhận được "loại chung loại bất hợp pháp cho instanceof"?

public class C<T> { 
    private class D { 
     public boolean equals(Object o) { 
      if (!(o instanceof D)) // line 4 
       return false; 
      D other = (D)o;    // line 6 
      return i == other.i; 
     } 
     int i; 
    } 
} 

tôi nhận được:

C.java:4: illegal generic type for instanceof 
      if (!(o instanceof D)) 
          ^

Tôi cũng nhận được một "diễn viên không được kiểm soát" cảnh báo về dòng 6. Tại sao? okhông phải loại chung - nó chỉ là một đồng bằng Object. Làm thế nào tôi có thể triển khai chính xác equals() bằng cách kiểm tra và truyền tới một phiên bản D?

Lưu ý: Rõ ràng, ví dụ mã này là phiên bản được cắt xuống của mã thực tế của tôi. Các lớp thực tế cho CD lớn hơn nhiều và D là một lớp bên trong lớp C được sử dụng bởi việc triển khai.

FYI: D thực sự sử dụng thông số chung T.

+7

bạn đã thử * instanceof C.D * thay vì * instanceof D *? –

+0

Tôi sẽ lưu ý rằng ví dụ được cho là * bị hỏng. –

+0

@Evan: Nó hoạt động. Nhưng tại sao trình độ chuyên môn lại cần thiết? –

Trả lời

30

Các o không phải là một kiểu generic - nó chỉ là một đối tượng đơn giản.

Đó không phải là vấn đề. Vấn đề ... và nguyên nhân gốc rễ của cả hai lỗi biên dịch ... là D là một lớp chung. Và nó là chung chung vì nó là một lớp lồng nhau không tĩnh trong một lớp chung. Tên đầy đủ của nó sẽ là some.pkg.C<T>.D.

FYI: The real D không tận dụng các tham số T. generic

Và thực tế là nó có thể tận dụng T là những gì làm D một lớp chung.

Lý do bạn không thể sử dụng instanceof D hoặc (D) là loại xóa chung. Về cơ bản, thời gian chạy không thể phân biệt được giữa các loại (nói) C<String>.DC<Integer>.D. Và vì không thể thực hiện điều đó, nên không thể xác định xem instanceof D có nên trả lại true hoặc false hoặc nếu (D) thành công hay ném ClassCastException.

Một giải pháp sẽ là khai báo D là tĩnh. Nhưng điều đó sẽ không hoạt động với "D thực" của bạn bởi vì một lớp tĩnh không thể sử dụng một tham số kiểu generic từ lớp kèm theo. "FYI" của bạn nói rằng nó làm điều đó.

Một giải pháp khác là khởi tạo lớp bên ngoài C chuyển cho loại thực tế T làm ví dụ java.lang.Class<T>. Sau đó sử dụng cá thể Class này để triển khai kiểm tra kiểu và thời gian chạy theo yêu cầu. Điều này có thể là lộn xộn.

Giải pháp thứ ba là cẩn thận phân tích mã và xác định xem nó có an toàn cho @SuppressCảnh báo chú thích để chặn cảnh báo "không an toàn" hay không.

Loại tẩy xoá nào? 'o' là loại đối tượng trực tiếp.

Trên thực tế Object là loại tuyên bố của biến o. Đối tượng thực tế rất có thể sẽ có một số loại khác, và nó là rằng loại (nếu đó là ví dụ D) sẽ bị xóa loại.

7

Nếu bạn làm cho lớp bên trong tĩnh, thì mã sẽ biên dịch tốt.

Ex:

private static class D{...} 

đọc here cho sự khác biệt.

Bạn cũng có thể thử o.getClass() != D.class (sau khi bảo vệ chống lại o là null, tất nhiên)

+0

Tôi biết sự khác biệt giữa các lớp lồng nhau không tĩnh và tĩnh. Trong trường hợp này, tôi cần nó không tĩnh. Nếu tôi làm cho lớp lồng nhau tĩnh, tôi không thể sử dụng tham số generic T. –

+1

Điều gì về các phép so sánh o.getClass() và D.class? Bạn sẽ không biết rằng chúng thuộc cùng một kiểu được tham số hóa, nhưng tôi không chắc chắn rằng bạn có thể thực hiện điều đó một cách đáng tin cậy bằng cách xóa kiểu. –

+0

Loại xóa gì? 'o' là loại đối tượng trực tiếp. –

3
D.class.isInstance(o) 

dường như hoạt động ở đây.

6

@StephenC đúng trong vấn đề là D có nghĩa là C<T>.D, là loại được tham số hóa. Các giải pháp là sử dụng các loại nguyên liệu hoặc loại wildcard-tham số:

if (!(o instanceof C.D)) 

hoặc

if (!(o instanceof C<?>.D)) 
Các vấn đề liên quan