2010-10-09 53 views
6

Trong đoạn mã sau, kiểu x là I (mặc dù x cũng thực hiện J nhưng không biết tại thời gian biên dịch) vậy tại sao mã ở (1) không dẫn đến lỗi biên dịch. Bởi vì tại thời gian biên dịch chỉ có loại tham chiếu được xem xét.Tại sao mã instanceof này hoạt động và không gây ra lỗi thời gian biên dịch?

public class MyClass { 
    public static void main(String[] args) { 
     I x = new D(); 
     if (x instanceof J) //(1) 
      System.out.println("J"); 
    } 
} 

interface I {} 

interface J {} 

class C implements I {} 

class D extends C implements J {} 
+1

Lưu ý phụ - xin đừng quên thêm thẻ cho ngôn ngữ. Tôi đã thêm "java" cho bạn. – EboMike

+0

xin lỗi tôi cần có – user439526

Trả lời

12

instanceof được sử dụng để xác định thời gian chạy kiểu của đối tượng. Bạn đang cố gắng xác định xem x thực sự là đối tượng của loại J khi chương trình đang chạy, do đó, nó biên dịch.

Bạn có nghĩ rằng nó sẽ dẫn đến lỗi biên dịch vì bạn nghĩ trình biên dịch không biết loại của x?

Sửa

Như Kirk Woll đã comment (nhờ Kirk Woll!), Nếu bạn đang kiểm tra nếu x là một instanceof một lớp bê tông, và trình biên dịch có thể xác định x 's loại, sau đó bạn sẽ nhận được một lỗi tại thời gian biên dịch.

Từ ngôn ngữ Java Specification:

Nếu một dàn diễn viên của RelationalExpression đến ReferenceType sẽ bị từ chối là một lỗi thời gian biên dịch, thì biểu thức quan hệ instanceof tương tự như vậy tạo ra một lỗi thời gian biên dịch. Trong tình huống như vậy, kết quả của biểu thức instanceof không bao giờ có thể đúng.

Như một ví dụ về điều này:

import java.io.Serializable; 
import java.io.IOException; 
import java.io.ObjectOutputStream; 
import java.io.ObjectInputStream; 

class SerializableClass implements Serializable 
{ 
    private writeObject(ObjectOutputStream out) {} 
    private readObject(ObjectInputStream in) {} 
} 

public class DerivedSerializableClass extends SerializableClass 
{ 
    public static void main(String[] args) 
    { 
     DerivedSerializableClass dsc = new DerivedSerializableClass(); 

     if (dsc instanceof DerivedSerializableClass) {} // fine 
     if (dsc instanceof Serializable) {} // fine because check is done at runtime 
     if (dsc instanceof String) {} // error because compiler knows dsc has no derivation from String in the hierarchy 

     Object o = (Object)dsc; 
     if (o instanceof DerivedSerializableClass) {} // fine because you made it Object, so runtime determination is necessary 
    } 
} 
+1

+1 và nếu nó * không phải * một nhà điều hành thời gian chạy, điều gì trên trái đất sẽ là điểm của nó? Các câu lệnh 'if' sử dụng nó sẽ không có ý nghĩa gì cả. –

+0

Cũng từ những gì tôi đọc có một kiểm tra thời gian biên dịch ban đầu khi sử dụng toán tử instanceof để xác định xem nguồn và đích có mối quan hệ kiểu siêu kiểu phụ hay không. Sau đó, đối tượng thực tế của nguồn được sử dụng để xác định xem nguồn có phải là loại phụ của loại Đích hay không. – user439526

+1

Vui lòng sửa lại sự hiểu biết của tôi về cách thức hoạt động của tính năng này. Vì vậy, trong đoạn mã này mặc dù đối tượng được tham chiếu bởi x là một kiểu con của J nhưng không có mối quan hệ nào giữa I và J. Vì vậy x là loại I trong đoạn mã trên, tức là tôi x = new D() ;, nên chơi này một vai trò tại thời gian biên dịch? – user439526

2

instanceof là một nhà điều hành thời gian chạy, không thời gian biên dịch, vì vậy nó được đánh giá bằng cách sử dụng loại thực tế của đối tượng đang được tham chiếu.

+0

Nhưng nó có thể tạo ra các lỗi biên dịch. .. – EJP

+0

Vâng, nếu nó nhận được đầu vào tĩnh (tức là các lớp thay vì tham chiếu). Tôi nên chỉnh sửa câu trả lời của mình, mặc dù kuropenguin đã đưa ra một câu trả lời rất đầy đủ, do đó, đó là tranh luận. – EboMike

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