100

为什么这段代码不能编译?

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

为什么我不能将类变量传递给instanceof

4

4 回答 4

142

instanceof运算符适用于引用类型,如Integer,而不适用于对象,如new Integer(213). 你可能想要类似的东西

clazz.isInstance(obj)

旁注:如果你写,你的代码会更简洁

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

不过,不确定您是否需要一种方法。

于 2010-04-07T07:24:11.540 回答
15

instanceof只能与显式类名一起使用(在编译时说明)。为了进行运行时检查,您应该执行以下操作:

clazz.isInstance(obj)

这有一个小的优势,clazz.isAssignableFrom(..)因为它可以更好地处理案例obj == null

于 2010-04-07T07:28:03.117 回答
5

正如其他人所提到的,您不能将类变量传递给,instanceof因为类变量引用Object的实例,而右手instanceof必须是type。也就是说,instanceof并不表示“y 是对象 x 的实例”,而是表示“y 是类型 X 的实例”。如果您不知道对象和类型之间的区别,请考虑:

Object o = new Object();

在这里,类型是Object,并且o是对具有该类型的 Object 实例的引用。因此:

if(o instanceof Object)

有效但

if(o instanceof o)

不是因为o右边是一个对象,而不是一个类型。

更具体到您的情况,类实例不是类型,它是一个对象(由 JVM 为您创建)。在你的方法中,Class是一个类型,但是clazz是一个对象(嗯,一个对象的引用)

您需要一种将对象与类对象进行比较的方法。事实证明,这很受欢迎,因此作为 Class Object: 的方法提供给您isInstance()

这是 isInstance 的 Java Doc,它更好地解释了这一点:

public boolean isInstance(Object obj)

确定指定的 Object 是否与该 Class 表示的对象赋值兼容。此方法是 Java 语言 instanceof 运算符的动态等效方法。如果指定的 Object 参数不为 null,则该方法返回 true,并且可以强制转换为此 Class 对象表示的引用类型,而不会引发 ClassCastException。否则返回 false。

具体来说,如果此 Class 对象表示已声明的类,则如果指定的 Object 参数是表示的类(或其任何子类)的实例,则此方法返回 true;否则返回 false。如果此 Class 对象表示一个数组类,如果指定的 Object 参数可以通过恒等转换或扩展引用转换转换为数组类的对象,则此方法返回 true;否则返回 false。如果此 Class 对象表示一个接口,则如果指定 Object 参数的类或任何超类实现此接口,则此方法返回 true;否则返回 false。如果此 Class 对象表示原始类型,则此方法返回 false。

参数: obj - 要检查的对象
返回:如果 obj 是此类的实例,则返回 true
自: JDK1.1

于 2013-07-02T16:23:10.747 回答
3

首先,instanceof要求右边的操作数是一个实际的类(例如obj instanceof Objector obj instanceof Integer)而不是类型的变量Class。其次,你犯了一个相当常见的新手错误,你真的不应该这样做......以下模式:

如果(条件表达式){
    返回真;
} 别的{
    返回假;
}

以上可以重构为:

返回条件表达式

您应该始终执行该重构,因为它消除了多余的 if...else 语句。同样,表达式可重构为相同的结果。return conditional_expression ? true : false;

于 2010-04-07T07:29:53.067 回答