Tại sao một biến "Lớp" không thể được chuyển cho instanceof?


89

Tại sao mã này không biên dịch?

    public boolean isOf(Class clazz, Object obj){
        if(obj instanceof clazz){
            return true;
        }else{
            return false;
        }
    }

Tại sao tôi không thể chuyển một biến lớp cho instanceof?

Câu trả lời:


131

Các instanceofnhà điều hành hoạt động trên các loại tài liệu tham khảo, như Integer, không phải trên các đối tượng, như new Integer(213). Bạn có thể muốn một cái gì đó như

clazz.isInstance(obj)

Lưu ý phụ: mã của bạn sẽ ngắn gọn hơn nếu bạn viết

public boolean isOf(Class clazz, Object obj){
    return clazz.isInstance(obj)
}

Tuy nhiên, không thực sự chắc chắn nếu bạn cần một phương pháp nữa.


Tôi biết mã là hoàn toàn vô dụng, tôi chỉ muốn chứng minh sự nhầm lẫn của tôi :)
eric2323223

6
Integerkhông một chữ lớp. Integer.classsẽ là một lớp chữ (xem § 15.8.2 của JLS: java.sun.com/docs/books/jls/third_edition/html/… ). Các instanceofnhà khai thác phải mất một "ReferenceType" (hay còn gọi là một loại tên) theo quy định § 15.20.2 của JLS: java.sun.com/docs/books/jls/third_edition/html/...
Joachim Sauer

3
Tôi sẽ sử dụng clazz.isInstance(obj)vì đối tượng đã được cung cấp.
Donal Fellows

13

instanceofchỉ có thể được sử dụng với các tên lớp rõ ràng (được nêu tại thời điểm biên dịch). Để thực hiện kiểm tra thời gian chạy , bạn nên làm:

clazz.isInstance(obj)

Điều này có một lợi thế nhỏ hơn clazz.isAssignableFrom(..)vì nó xử lý trường hợp obj == nulltốt hơn.


5

Như những người khác đã đề cập, bạn không thể chuyển một biến lớp đến instanceofvì một biến lớp tham chiếu đến một thể hiện của Đối tượng , trong khi bên phải của instanceofphải là một kiểu . Điều đó instanceofkhông có nghĩa là "y là một thể hiện của Đối tượng x", nó có nghĩa là "y là một thể hiện của kiểu X". Trong trường hợp bạn không biết sự khác biệt giữa Object và type, hãy xem xét:

Object o = new Object();

Ở đây, kiểu là Object, và olà một tham chiếu đến thể hiện của Đối tượng với kiểu đó. Như vậy:

if(o instanceof Object)

là hợp lệ nhưng

if(o instanceof o)

không phải vì oở phía bên tay phải là Đối tượng, không phải là một loại.

Cụ thể hơn cho trường hợp của bạn, một cá thể lớp không phải là một kiểu, nó là một Đối tượng (được tạo cho bạn bởi JVM). Trong phương thức của bạn, Classlà một kiểu, nhưng clazzlà một Đối tượng (tốt, một tham chiếu đến một Đối tượng)

Những gì bạn cần là một cách để so sánh một Đối tượng với một Đối tượng Lớp. Nó chỉ ra rằng đây là phổ biến vì vậy đây được cung cấp cho bạn như là một phương pháp của đối tượng Class: isInstance().

Đây là Tài liệu Java cho isInstance, giải thích điều này tốt hơn:

public boolean isInstance(Object obj)

Xác định xem Đối tượng được chỉ định có tương thích với phép gán với đối tượng được Đại diện bởi Lớp này hay không. Phương thức này là tương đương động của toán tử instanceof của ngôn ngữ Java. Phương thức trả về true nếu đối số Đối tượng được chỉ định không phải là giá trị rỗng và có thể được chuyển thành kiểu tham chiếu được đại diện bởi đối tượng Lớp này mà không cần nâng cao một ClassCastException. Ngược lại, nó trả về false.

Cụ thể, nếu đối tượng Lớp này đại diện cho một lớp đã khai báo, phương thức này trả về true nếu đối số Đối tượng được chỉ định là một thể hiện của lớp được đại diện (hoặc của bất kỳ lớp con nào của nó); ngược lại nó trả về false. Nếu đối tượng Lớp này đại diện cho một lớp mảng, phương thức này trả về true nếu đối số Đối tượng được chỉ định có thể được chuyển đổi thành một đối tượng của lớp mảng bằng một chuyển đổi danh tính hoặc bằng một chuyển đổi tham chiếu mở rộng; ngược lại nó trả về false. Nếu đối tượng Lớp này đại diện cho một giao diện, phương thức này trả về true nếu lớp hoặc bất kỳ lớp cha nào của đối số Đối tượng được chỉ định triển khai giao diện này; ngược lại nó trả về false. Nếu đối tượng Class này đại diện cho một kiểu nguyên thủy, phương thức này trả về false.

Tham số: obj - đối tượng cần kiểm tra
Trả về: true nếu obj là một thể hiện của lớp này
Kể từ: JDK1.1


3

Thứ nhất, instanceofyêu cầu toán hạng ở bên phải là một lớp thực tế (ví dụ obj instanceof Objecthoặc obj instanceof Integer) và không phải là một biến kiểu Class. Thứ hai, bạn đã mắc một lỗi khá phổ biến cho người mới bắt đầu mà bạn thực sự không nên làm ... mô hình sau:

if ( biểu_thức có điều kiện ) {
    trả về true;
} khác {
    trả về sai;
}

Phần trên có thể được cấu trúc lại thành:

trả về biểu_thức có điều kiện ;

Bạn nên luôn thực hiện việc tái cấu trúc đó, vì nó loại bỏ câu lệnh if ... else dư thừa. Tương tự, biểu thức có thể cấu trúc lại cho cùng một kết quả.return conditional_expression ? true : false;


2
Đó không phải là sai lầm. Có thể vụng về nhưng hoàn toàn ổn. Có thể bạn muốn có mã bổ sung trước khi quay lại trong tương lai gần ...
Đáng kinh ngạc ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.