为什么不能将“ Class”变量传递给 instanceof?

为什么这段代码无法编译?

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

为什么我不能传递一个类变量到 instanceof

37590 次浏览

The instanceof operator works on reference types, like Integer, and not on objects, like new Integer(213). You probably want something like

clazz.isInstance(obj)

Side note: your code will be more concise if you write

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

Not really sure if you need a method anymore ,though.

instanceof can be used only with explicit class names (stated at compile time). In order to do a runtime check, you should do:

clazz.isInstance(obj)

This has a small advantage over clazz.isAssignableFrom(..) since it deals with the case obj == null better.

Firstly, instanceof requires that the operand on the right is an actual class (e.g. obj instanceof Object or obj instanceof Integer) and not a variable of type Class. Secondly, you have made a fairly common newbie mistake that you really should not do... the following pattern:

if ( conditional_expression ){
return true;
} else{
return false;
}

The above can be refactored into:

return conditional_expression;

You should always perform that refactoring, as it eliminates a redundant if...else statement. Similarly, the expression return conditional_expression ? true : false; is refactorable to the same result.

As others have mentioned, you cannot pass a class variable to instanceof because a class variable references an instance of an Object, while the right hand of instanceof has to be a type. That is, instanceof does not mean "y is an instance of Object x", it means "y is an instance of type X". In case you don't know the difference between an Object and a type, consider:

Object o = new Object();

Here, the type is Object, and o is a reference to the instance of the Object with that type. Thus:

if(o instanceof Object)

is valid but

if(o instanceof o)

is not because o on the right hand side is an Object, not a type.

More specific to your case, a class instance is not a type, it is an Object (which is created for you by the JVM). In your method, Class is a type, but clazz is an Object (well, a reference to an Object)

What you need is an way to compare an Object to a Class Object. It turns out that this is popular so this is provided to you as a method of the Class Object: isInstance().

Here is the Java Doc for isInstance, which explains this better:

public boolean isInstance(Object obj)

Determines if the specified Object is assignment-compatible with the object represented by this Class. This method is the dynamic equivalent of the Java language instanceof operator. The method returns true if the specified Object argument is non-null and can be cast to the reference type represented by this Class object without raising a ClassCastException. It returns false otherwise.

Specifically, if this Class object represents a declared class, this method returns true if the specified Object argument is an instance of the represented class (or of any of its subclasses); it returns false otherwise. If this Class object represents an array class, this method returns true if the specified Object argument can be converted to an object of the array class by an identity conversion or by a widening reference conversion; it returns false otherwise. If this Class object represents an interface, this method returns true if the class or any superclass of the specified Object argument implements this interface; it returns false otherwise. If this Class object represents a primitive type, this method returns false.

Parameters: obj - the object to check
Returns: true if obj is an instance of this class
Since: JDK1.1