2015-07-14 18 views
85

Tôi muốn biết về hành vi sau của toán tử instanceof trong Java.Toán tử 'instanceof' hoạt động khác nhau đối với giao diện và lớp học

interface C {} 

class B {} 

public class A { 
    public static void main(String args[]) { 
     B obj = new B(); 
     System.out.println(obj instanceof A);  //Gives compiler error 
     System.out.println(obj instanceof C);  //Gives false as output 
    } 
} 

Tại sao lại như vậy? Không có mối quan hệ giữa interface Cclass B, nhưng nó cho sai trong khi trong trường hợp obj instanceof A nó cho lỗi trình biên dịch?

+12

Lưu ý: nếu bạn thay đổi nó thành 'Object obj = new B()', nó biên dịch. – immibis

+1

Lỗi trình biên dịch cho bạn biết điều gì? – karfau

+0

Nếu 'lớp B' là' final' thì 'obj instanceof C' sẽ không biên dịch, bởi vì nếu' B' không có kiểu con, thì nó được đảm bảo không liên quan đến 'C'. – jaco0646

Trả lời

122

Vì Java không thừa kế nhiều lớp, nó hoàn toàn được biết đến trong quá trình biên dịch mà obj đối tượng thuộc loại B không thể là loại phụ của A. Mặt khác, nó có thể có thể subtype của giao diện C, ví dụ như trong trường hợp này:

interface C {} 

class B {} 

class D extends B implements C {} 

public class A { 
    public static void main(String args[]) { 
     B obj = new D(); 
     System.out.println(obj instanceof C);  //compiles and gives true as output 
    } 
} 

Vì vậy, chỉ nhìn vào obj instanceof C biểu trình biên dịch không thể nói trước cho dù đó sẽ là đúng hay sai, nhưng nhìn vào obj instanceof A nó biết rằng điều này luôn luôn là sai, do đó vô nghĩa và giúp bạn ngăn chặn một lỗi. Nếu bạn vẫn muốn có séc vô nghĩa này trong chương trình của bạn, bạn có thể thêm một đúc rõ ràng để các Object:

System.out.println(((Object)obj) instanceof A);  //compiles fine 
+1

Các hương vị khác của một kiểm tra vô nghĩa là sử dụng 'A.class.isAssignableFrom (obj.getClass())' –

+0

Tôi hơi bối rối với lời giải thích của bạn, bạn nói 'Java không có thừa kế nhiều lớp' có tôi đồng ý nhưng làm thế nào nó là áp dụng trong trường hợp này bởi vì không phải B hoặc A mở rộng anyting vậy tại sao nhiều di sản ở đây. Nó sẽ là hữu ích nếu bạn có thể giải thích? – codegasmer

+0

@codegasmer Câu trả lời trễ: Nếu Java cho phép một lớp kế thừa từ nhiều lớp khác, thì người ta có thể làm "lớp D mở rộng A, B" hoặc một số như vậy, và sau đó "B obj = new D()", và làm cho " obj instanceof A "trong bản dịch câu hỏi ban đầu (trong khi nó hiện không) - trong thực tế nó đã biên dịch tốt hơn, bởi vì nó sẽ được dự kiến ​​sẽ đánh giá là đúng. Nhưng nếu nó không được phép cho bất cứ thứ gì là cả B và A, thì biểu thức "obj instanceof A" trong đó obj được định nghĩa là loại B có thể được coi là vô lý. – mjwach

0

Bằng việc sử dụng final modifier trong khai báo lớp dưới đây, nó được đảm bảo rằng không thể có một lớp con của Test, có thể triển khai giao diện Foobar. Trong trường hợp này, rõ ràng là TestFoobar không tương thích với nhau:

public final class Test { 

    public static void main(String[] args) { 
     Test test = new Test(); 
     System.out.println(test instanceof Foobar); // Compiler error: incompatible types 
    } 
} 

interface Foobar { 
} 

Ngược lại, nếu Test không được khai báo final, nó có thể được có thể là một lớp con của Test thực hiện giao diện. Và đó là lý do tại sao trình biên dịch sẽ cho phép câu lệnh test instanceof Foobar trong trường hợp này.

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