What is the difference between instanceof and Class.isAssignableFrom(...)?
When using instanceof
, you need to know the class of B
at compile time. When using isAssignableFrom()
it can be dynamic and change during runtime.
java: Class.isInstance vs Class.isAssignableFrom
clazz.isAssignableFrom(Foo.class)
will be true whenever the class represented by the clazz
object is a superclass or superinterface of Foo
.
clazz.isInstance(obj)
will be true whenever the object obj
is an instance of the class clazz
.
That is:
clazz.isAssignableFrom(obj.getClass()) == clazz.isInstance(obj)
is always true so long as clazz
and obj
are nonnull.
Class#isInstance vs Class#isAssignableFrom
isAssignableFrom
also tests whether the type can be converted via an identity conversion or via a widening reference conversion.
Class<?> cInt = Integer.TYPE;
Long l = new Long(123);
System.out.println(cInt.isInstance(l)); // false
System.out.println(cInt.isAssignableFrom(cInt)); // true
instanceof fails but isInstance() and isAssignableFrom() work?
x instanceof Y
only compiles if the compile-time type of x
is compatible with Y
. For example, the code below doesn't compile because no String
is a Number
.
String str = "Foo";
System.out.println(str instanceof Number);
In your case, responseClass
is a Class
, not a ThisClass
so
responseClass instanceof Class
compiles, and gives true
, whereas
responseClass instanceof ThisClass
doesn't compile. You should use isInstance
.
Java isInstance vs instanceOf operator
This is so that I can really flexibly assign the query return type in the actual helper.
There is nothing flexible about the return type of this method
static <T> QueryHelper getQueryHelper (Class<T> expectedReturn) {
if (expectedReturn.isInstance (SomeRelatedClass.class))
return query1;
else
return query2;
}
It will always return an instance of QueryHelper
. If you want the return type to be flexible you would need to define it as something like:
static <T> T getQueryHelper (Class<T> expectedReturn) {
}
Now the return type is flexible, because it will depend on the type of the argument
And the real heart of this is that I don't understand the difference between class.isInstance and the instanceOf operator?
The difference is that instanceof does a type-check that is fixed at compile-time, for example:
static boolean isInstance(Object myVar) {
return (myVar instanceof Foo);
}
will always check that myVar is an instance of Foo, whereas
static <T> boolean isInstance(Object myVar, Class<T> expectedType) {
return expectedType.isInstance(myVar);
}
will check that myVar is an instance of expectedType, but expectedType can be a different type each time the method is called
What is the difference between the 'instanceof' and 'in' keywords?
The main difference is that instanceof
is a Java keyword, while obj in SomeClass
is an equivalent of SomeClass.isCase(obj)
method call as you mentioned in your question.
There is one major implication: instanceof
cannot be overridden and as Oracle docs says:
The
instanceof
operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.
Source: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html
Class.isCase(obj)
is implemented as follows:
/**
* Special 'Case' implementation for Class, which allows testing
* for a certain class in a switch statement.
* For example:
* <pre>switch( obj ) {
* case List :
* // obj is a list
* break;
* case Set :
* // etc
* }</pre>
*
* @param caseValue the case value
* @param switchValue the switch value
* @return true if the switchValue is deemed to be assignable from the given class
* @since 1.0
*/
public static boolean isCase(Class caseValue, Object switchValue) {
if (switchValue instanceof Class) {
Class val = (Class) switchValue;
return caseValue.isAssignableFrom(val);
}
return caseValue.isInstance(switchValue);
}
Source: org/codehaus/groovy/runtime/DefaultGroovyMethods.java#L1121
As you can see based on the source code Groovy's obj in SomeClass
is not an alias to instanceof
, because it does a bit more. However, there is one important thing worth mentioning - you can override isCase()
implementation, but you can't change how instanceof
Java keyword behaves. Overriding Class.isCase()
may cause some damage to your code if you use it as an alternative to Java's instanceof
keyword.
Using instanceof to seperate classes in an ArrayList
I'm not sure what Packable
is, but you appear to be confused about a few concepts here.
In java, Packable reference
does not represent the Packable
concept. It represents a specific instance of Packable (or null).
In other words, given Dog dog
, that means dog is some specific dog. Not 'the general concept of a dog'. We know that the specific animal that dog
is referring to is, at least, a Dog. It could be Fifi, the neighbour's schnauzer.
instanceof
, on the other hand, is about the general concept of things: if (fifi instanceof Dog)
is how you're supposed to use it. You're more or less attempting to do the equivalent of if (fifi instanceof rover)
which just doesn't make sense. How can one dog be 'an instance' of another? It's not that the answer is 'true' or 'false', but that the very question doesn't even make sense, which is why javac doesn't compile it. It has no idea what this even means.
Java, being java, makes objects of many things. Notably including the very notion of things. Thus, there is the class java.lang.Class
, instances of which represent classes. A bit of alice-going-down-the-rabbit-hole thing is happening here: Classes as a concept are also represented as instances of the java.lang.Class
class.
A class OBJECT (so, an instance of java.lang.Class
) has the .isAssignableFrom
method. This in fact takes another j.l.CLass
as argument, it's for checking if one type is a subtype of another. In that sense, the question linked is needlessly confusing - you're really looking for the instanceOf method (there is an instanceof
language construct, but the j.l.Class
class has an isInstance
method, which is unrelated, other than that they roughly accomplish the same goal: Check if some INSTANCE is of a type that is equal to, or a subtype of, some TYPE.
This is an example of how to use it:
Class<?> c = Number.class;
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
this is more or less equivalent to:
Object o = Integer.valueOf(5);
System.out.println(o instanceof Number);
Except now the Number
part no longer needs to be written at 'write the code' time, you can supply it, say, read it from a parameter. You'd have to, of course, dynamically construct the Class instance. You can do so either by string-lookup, or by getting the actual type of an actual object. For example:
String input = scanner.next(); // user types in "java.lang.Number"
Class<?> c = Class.forName(input);
Object o = Integer.valueOf(5);
System.out.println(c.isInstance(o));
Or:
Object i = Integer.valueOf(5);
Object d = Double.valueOf(10);
Class<?> c = i.getClass(); // will be java.lang.Integer.class
System.out.println(c.isInstance(d)); // false
But doing this latter bit is really dangerous. Often i.getClass()
returns some hidden impl detail subtype (java is hierarchical and object oriented, anywhere, say, an ArrayList is needed, someone is free to make a new class: class MyVariantOfArrayList extends ArrayList
, and use that - now you write ArrayList foo = getList()
, but foo.getClass()
doesn't return ArrayList - no, you invoke that method on the object the foo
variable points at, so, it'd be MyVariantOfArrayList.class
, not ArrayList.class
.
It's possible Packable
itself represents a type. But then it either needs to also have isInstance
and isAssignableFrom
and such (and you need to start questioning why you're badly reinventing the wheel here - java.lang.Class already exists!), or it needs a .getRepresentedClass()
method. You can't call it .getClass()
, as the JVM has already given all objects that method, and it would return Packable.class
itself.
Cannot find the Type of class to use with instanceOf
instanceof
only works with literal classes, not with Class
objects.
Class.isInstance
You must call the isInstance
method on Class
class. Do not confuse with instanceOf
.
class0.isInstance(rootCause)
Related Topics
Differencebetween Thread.Start() and Thread.Run()
Spring Data JPA - Zoneddatetime Format for JSON Serialization
.Toarray(New Myclass[0]) or .Toarray(New Myclass[Mylist.Size()])
How to Calculate "Time Ago" in Java
Encode Base64 Cannot Find Symbol Error
How to Instantiate a Class by Name in Java
How to Map Calculated Properties with JPA and Hibernate
Eclipse Exported Runnable Jar Not Showing Images
How to Share Data with Two(2) Swingworker Class in Java
If Profiler Is Not the Answer, What Other Choices Do We Have
How to Stop a Java Thread Gracefully
What Are the Differences Between the Different Saving Methods in Hibernate
Ignoring New Fields on JSON Objects Using Jackson
Java String Replace Not Working