java: Class.isInstance vs Class.isAssignableFrom


232

Hãy clazzlà một số Classobjlà một số Object.

clazz.isAssignableFrom(obj.getClass())

luôn luôn giống như

clazz.isInstance(obj)

?

Nếu không, sự khác biệt là gì?


25
nếu obj == null, cái thứ hai trả về false, cái thứ nhất thì không. ;)
Peter Lawrey

21
@PeterLawrey, người đầu tiên sẽ ném NullPointerExceptionnếu obj == null.
ry Bổ trợ

Tìm thấy một số câu trả lời với các mẫu từ hrere: mytechnotes.biz/2012/07/ từ
Paramesh Korrakuti

4
Đối với độc giả: bạn sắp bước vào một hố đen sâu, tối, từ đó bạn sẽ không bao giờ thoát ra được. Sự khác biệt là vô tận. Bỏ cuộc ngay bây giờ trong khi bạn vẫn có thể: stackoverflow.com/q/496928/1599699
Andrew

@ParameshKorrakuti tên miền được thay đổi để tshikatshikaaa.blogspot.com/2012/07/...
Jérôme Verstrynge

Câu trả lời:


222

clazz.isAssignableFrom(Foo.class)sẽ đúng bất cứ khi nào lớp được đại diện bởi clazzđối tượng là siêu lớp hoặc siêu giao diện của Foo.

clazz.isInstance(obj)sẽ đúng bất cứ khi nào đối tượng objlà một thể hiện của lớp clazz.

Đó là:

clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)

luôn luôn đúng cho đến khi clazzobjkhông còn nguyên vẹn.


3
điều này bỏ lỡ trường hợp Foo giống như clazz - trong trường hợp nó trả về đúng: câu trả lời được bình chọn hàng đầu của Pauls dưới đây đã sửa điều này
hoàng

3
Tôi đồng ý rằng khi clazz là một Foo, thì clazz.isAssignableFrom (Foo. Class) là đúng. Tôi đã nói khác ở đâu?
uckelman

5
@Gili Đây không phải là những gì uckelman nói. Xin vui lòng đọc lại câu trả lời của anh ấy.
Puce

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); -> nó cũng đúng cho các giao diện.
Puce

1
Kỹ thuật: Nếu objnullsau đó clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)sẽ ném một NullPointerExceptionvà không trở lại true.
Andrew Macheret

196

Cả hai câu trả lời đều ở trong sân bóng nhưng không phải là một câu trả lời hoàn chỉnh.

MyClass.class.isInstance(obj)là để kiểm tra một ví dụ. Nó trả về true khi tham số obj không phải là null và có thể được truyền tới MyClassmà không tăng a ClassCastException. Nói cách khác, obj là một thể hiện của MyClasshoặc các lớp con của nó.

MyClass.class.isAssignableFrom(Other.class)sẽ trả về true nếu MyClassgiống như, hoặc siêu lớp hoặc siêu giao diện của , Other. Othercó thể là một lớp hoặc một giao diện. Nó trả lời đúng nếu Othercó thể được chuyển đổi thành a MyClass.

Một ít mã để chứng minh:

public class NewMain
{
    public static void main(String[] args)
    {
        NewMain nm = new NewMain();
        nm.doit();
    }

    class A { }

    class B extends A { }

    public void doit()
    {
        A myA = new A();
        B myB = new B();
        A[] aArr = new A[0];
        B[] bArr = new B[0];

        System.out.println("b instanceof a: " + (myB instanceof A)); // true
        System.out.println("b isInstance a: " + A.class.isInstance(myB)); //true
        System.out.println("a isInstance b: " + B.class.isInstance(myA)); //false
        System.out.println("b isAssignableFrom a: " + A.class.isAssignableFrom(B.class)); //true
        System.out.println("a isAssignableFrom b: " + B.class.isAssignableFrom(A.class)); //false
        System.out.println("bArr isInstance A: " + A.class.isInstance(bArr)); //false
        System.out.println("bArr isInstance aArr: " + aArr.getClass().isInstance(bArr)); //true
        System.out.println("bArr isAssignableFrom aArr: " + aArr.getClass().isAssignableFrom(bArr.getClass())); //true
    }
}

10
Tại sao trong ví dụ của bạn "b isAssignableFrom a:" nhưng mã là A.class.isAssignableFrom(B.class)? Tôi bối rối bởi đầu ra :)
Roman Truba

4
Ừm ... trong tất cả các ví dụ của bạn "instanceOf" trả về đúng iff "isAssignableFrom" trả về đúng ... Tôi không thấy sự khác biệt theo cách này.
nhà phát triển Android

2
Hãy cẩn thận văn bản được in ra không khớp với mã và có thể gây nhầm lẫn ... Ví dụ: "System.out.println (" b isAssignableFrom a: "+ A. class.isAssignableFrom (B. class));"
Polster

21
@Paul Câu trả lời là không hữu ích vì người đọc không khỏi thắc mắc "sự khác biệt giữa một đối tượng là một thể hiện của một lớp con của một lớp và loại đối tượng có thể chuyển đổi thành lớp là gì?" Chắc chắn, bạn có thể thấy rằng bạn đã để lại cho người đọc nhiều câu hỏi sau khi đọc câu trả lời của bạn như khi đến trang này. Một câu trả lời tốt hơn sẽ thực sự giải thích sự khác biệt (hoặc thiếu nó). Nếu không có sự khác biệt, câu trả lời nên nêu trực tiếp, "không có sự khác biệt thực tế".
Alexanderr Dubinsky

2
Quan trọng hơn, người đọc không biết nên dùng cái quái gì cho mục đích của họ. Theo các ý kiến ​​trong câu hỏi, isAssignableFrom()ném a NullPointerExceptionnếu đối tượng là null, trong khi isInstance()chỉ trả về false. Đó là câu trả lời thực sự.
Andrew

6

Tôi nghĩ rằng kết quả cho hai người đó phải luôn giống nhau. Sự khác biệt là bạn cần một thể hiện của lớp để sử dụng isInstancenhưng chỉ cần Classđối tượng sử dụng isAssignableFrom.


Điều này không đúng 100%. Comparable.class.isAssignableFrom(Byte.class) == truenhưng Byte.class.isInstance(Comparable.class) == false. Nói cách khác, isInstance()không đối xứng cho các giao diện, chỉ dành cho các lớp con.
Gili

6
@Gili: Bạn đã có một chút sai ở đó. Byte.class.isInstance(Comparable.class)là sai vì một Classđối tượng không phải là một thể hiện của Byte. So sánh đúng Comparable.class.isAssignableFrom(Byte.class)Comparable.class.isInstance((byte) 1), đó là sự thật.
ColinD

1
Tôi không đồng ý. Nếu bạn tra cứu Javadoc, Bytebạn sẽ phát hiện ra nó mở rộng Numbervà là một lớp. (byte) 1không tương đương với Byte. Các cựu là một người nguyên thủy. Cái sau là một Class.
Gili

2
@Gili: autoboxing phôi nguyên thủy byteđến Bytevì kiểu tham số của isInstanceObject.
ColinD

2
Được chứ. Quan điểm ban đầu của tôi là các cuộc gọi không đối xứng chính xác với nhau, nhưng khi đọc lại câu trả lời của bạn, bạn không bao giờ đưa ra khẳng định này nên bạn đã đúng.
Gili

6

Để cho ngắn gọn, chúng ta có thể hiểu hai API này như dưới đây:

  1. X.class.isAssignableFrom(Y.class)

Nếu XYlà cùng một lớp, hoặc XYsiêu lớp hoặc siêu giao diện, hãy trả về true, ngược lại, false.

  1. X.class.isInstance(y)

Say ylà một thể hiện của lớp Y, nếu XYlà cùng một lớp, hoặc XYsiêu lớp hoặc siêu giao diện, trả về true, ngược lại, sai.

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.