java:Class.isInstance与Class.isAssignableFrom


232

clazz一些Classobj一些Object

clazz.isAssignableFrom(obj.getClass())

总是和

clazz.isInstance(obj)

如果没有,有什么区别?


26
如果obj == null,则第二个返回false,第一个不返回。;)
Peter Lawrey

21
@PeterLawrey,第一个将抛出NullPointerExceptionif obj == null
ryvantage 2014年

找到了一些答案的样品从里尔:mytechnotes.biz/2012/07/...
Paramesh Korrakuti

4
对读者来说:您将要进入一个深黑色的黑洞,您将永远无法逃脱。差异是无限的。现在,您仍然可以放弃:stackoverflow.com/q/496928/1599699
Andrew

@ParameshKorrakuti域名正在改变tshikatshikaaa.blogspot.com/2012/07/...
杰罗姆Verstrynge

Answers:


222

clazz.isAssignableFrom(Foo.class)只要该clazz对象表示的类是的超类或超接口,它将为true Foo

clazz.isInstance(obj)只要对象obj是类的实例,它将为true clazz

那是:

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

只要clazz并且obj为非null,就始终为真。


3
这错过了Foo与clazz相同的情况-在这种情况下,它返回true:Pauls最受好评的答案更正了这一点
Rhubarb

3
我同意当clazz是Foo时,那么clazz.isAssignableFrom(Foo.class)是正确的。我在哪里说呢?
uckelman

5
@吉利这不是乌克尔曼所说的。请重新阅读他的答案。
Puce 2014年

2
Byte b = 3; Comparable.class.isAssignableFrom(b.getClass()) == Comparable.class.isInstance(b)); ->对于接口也是如此。
Puce 2014年

1
技术性:如果objnull那么clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)就会抛出NullPointerException而不是返回true
安德鲁·麦克雷

196

这两个答案都在球场上,但都不是完整答案。

MyClass.class.isInstance(obj)用于检查实例。当参数obj为非null且可以在MyClass不引发a的情况下进行强制转换时,它返回true ClassCastException。换句话说,obj是MyClass或其子类。

MyClass.class.isAssignableFrom(Other.class)如果MyClass与相同,或者是的超类或超接口,则将返回true OtherOther可以是类或接口。如果Other可以转换为MyClass

一些代码来演示:

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
为什么在您的示例中“ b isAssignableFrom a:”却代码是A.class.isAssignableFrom(B.class)?我对输出感到困惑:)
Roman Truba 2014年

4
嗯,在您的所有示例中,“ instanceOf”都返回真,而“ isAssignableFrom”返回了真……我看不到这种区别。
Android开发人员

2
请注意,打印出的文本与代码不匹配,可能会造成混淆。例如:“ System.out.println(” b isAssignableFrom a:“ + A.class.isAssignableFrom(B.class));”
polster

21
@Paul的答案是没有用的,因为读者不禁要问:“对象是类的子类的实例,而对象的类型可转换为该类之间有什么区别?” 当然,您可以看到,阅读答案后,给读者留下了与到达此页面时一样多的问题。更好的答案实际上可以解释差异(或缺乏差异)。如果没有差异,答案应该直接说明“没有实际差异”。
Aleksandr Dubinsky'2

2
更重要的是,读者不禁要问到底要用些什么。根据问题中的注释,如果对象为null,则isAssignableFrom()抛出a NullPointerException,而isInstance()仅返回false。那才是真正的答案。
安德鲁

6

我认为这两个的结果应该总是相同的。区别在于您需要使用该类的实例,isInstance而仅Class需要使用该对象isAssignableFrom


这不是100%正确。Comparable.class.isAssignableFrom(Byte.class) == true但是Byte.class.isInstance(Comparable.class) == false。换句话说,isInstance()它对于接口不是对称的,仅对于子类是对称的。
吉利2014年

6
@吉利:你在这里有点不对劲。Byte.class.isInstance(Comparable.class)为false,因为Class对象不是的实例Byte。正确的比较Comparable.class.isAssignableFrom(Byte.class)就是Comparable.class.isInstance((byte) 1),这是真的。
ColinD

1
我不同意。如果您查找Javadoc,Byte则会发现它是扩展Number类。(byte) 1不等同于Byte。前者是原始的。后者是一类。
吉利2014年

2
@Gili:自动装箱将原始类型转换byte为,Byte因为的参数类型isInstanceObject
ColinD

2
好的。我的原始观点是,调用之间并不完全对称,但是重新读取您的答案后,您再也没有提出这个主张,所以您是对的。
吉利2014年

6

为简便起见,我们可以像下面这样理解这两个API:

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

如果XY是相同的类,或者XY的超类或超接口,则返回true,否则返回false。

  1. X.class.isInstance(y)

y是class的实例Y,如果XY是相同的类,或者XY的超类或超接口,则返回true,否则返回false。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.