How to I test if a is a subclass of b?
Class<?> a = A.class;
Class<?> b = B.class;
Are you looking for:
Super.class.isAssignableFrom(Sub.class)
If you want to know whether or not a Class extends another, use Class#isAssignableFrom(Class). For your example, it would be:
if(B.class.isAssignableFrom(A.class)) { ... }
If you're interested in whether or not an instance is of a particular type, use instanceof:
A obj = new A();
if(obj instanceof B) { ... }
Note that these will return true if the class/instance is a member of the type hierarchy and are not restrictive to direct superclass/subclass relationships. For example:
// if A.class extends B.class, and B.class extends C.class
C.class.isAssignableFrom(A.class); // evaluates to true
// ...and...
new A() instanceof C; // evaluates to true
If you want to check for direct superclass/subclass relationships, Tim has provided an answer as well.
You want to know if b is assignable from a:
b.isAssignableFrom(a);
Additionally, if you want to know that a is a direct subclass of b:
a.getSuperclass().equals(b);
Related
class A {}
class B {}
public class Demo {
public static void main(String[] args) {
A a = new A();
System.out.println(a instanceof B);
}
}
This code is giving compile time error.
How can I use instanceof to give false instead of compile time error when object is not an instance of class specified.
Java knows an A cannot be a B so it won't compile. If you change the line to
Object a = new A();
it will compile (and return false) as it can no longer tell if an Object can be cast into type B.
If class A and B are not related through inheritance, then compiler will throw an error when you try to perform a instanceof B
In your case, A is NOT a subclass of B, so you can't do an instanceof check like a instanceof B
But, if you change your classes like below:
class A {}
class B extends A {}
public static void main(String[] args) {
B b=new B();
System.out.println(b instanceof A);
}
Now b instanceof A will return true because B IS-A (type of) A
You can read the Java doc here on the same subject:
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.
You can use this :
System.out.println(a.getClass().equals(B.class));
Instead of :
System.out.println(a instanceof B);
Quoting JLS Sec 15.20.2:
If a cast (§15.16) of the RelationalExpression to the ReferenceType would be rejected as a compile-time error, then the instanceof relational expression likewise produces a compile-time error. In such a situation, the result of the instanceof expression could never be true.
(Where they are describing RelationalExpression instanceof ReferenceType)
You can't write B b = (B) a; either, because A and B are both classes (*), and are unrelated, in the sense that A does not directly or indirectly extend B, nor vice versa.
As such, a reference to an A can never contain an instance of a B, so it is nonsensical to test this. As such, the compiler stops you from testing this, as it likely indicates a logical error.
(*) You could write a instanceof B if B were an interface, because a might refer to a subclass of A which additionally implements B, e.g.
class ChildOfA extends A implements B {}
A a = new ChildOfA();
System.out.println(a instanceof B); // fine.
Given the following:
class ClassA
class ClassA1 extends ClassA
class ClassA2 extends ClassA
class ClassA3 extends ClassA
ClassA1 a1 = new ClassA1()
ClassA2 a2 = new ClassA2()
ClassA3 a3 = new ClassA3()
ClassA a = either a1, a2, or a3 (programmed to be randomly chosen by JVM)
If the reference to the subclass object (either 'a1', 'a2', or 'a3') is only assigned to the superclass reference variable 'a' at runtime, how can I write an 'if' statement that implements: if 'a' refers to a1, access a specified field of a1 (which is not inherited from a)? Any assistance on this would be appreciated.
Use the instanceof operator and casting.
if (a instanceof ClassA1) {
((ClassA1) a).someMethodThatsOnlyInA1();
}
Or you can use the instanceof operator.
if(a instanceof ClassA1) { ... }
Or you can use the isAssignableFrom method of the Class<> type.
if(ClassA1.class.isAssignableFrom(a.getClass())) { ... }
Both ways seem to do the same, however with instancof you should know the type at compile time, with isAssignableFrom you could check types dynamically at runtime, p.e.:
if(a1.getClass().isAssignableFrom(a2.getClass())) { ... }
The last example cannot be written with the instanceof operator.
Though be aware for NullPointerExceptions because getClass() is a method!
How to I test if a is a subclass of b?
Class<?> a = A.class;
Class<?> b = B.class;
Are you looking for:
Super.class.isAssignableFrom(Sub.class)
If you want to know whether or not a Class extends another, use Class#isAssignableFrom(Class). For your example, it would be:
if(B.class.isAssignableFrom(A.class)) { ... }
If you're interested in whether or not an instance is of a particular type, use instanceof:
A obj = new A();
if(obj instanceof B) { ... }
Note that these will return true if the class/instance is a member of the type hierarchy and are not restrictive to direct superclass/subclass relationships. For example:
// if A.class extends B.class, and B.class extends C.class
C.class.isAssignableFrom(A.class); // evaluates to true
// ...and...
new A() instanceof C; // evaluates to true
If you want to check for direct superclass/subclass relationships, Tim has provided an answer as well.
You want to know if b is assignable from a:
b.isAssignableFrom(a);
Additionally, if you want to know that a is a direct subclass of b:
a.getSuperclass().equals(b);
I'm aware that this could be a possible duplicate, but the other threads haven't solved my problem completely.
Let's say I have the following classes A and B which extend BasicClass.
public abstract class BasicClass {
// ...
}
public class A extends BasicClass {
// ...
}
public class B extends BasicClass {
// ...
}
And now I want to cast class A to B dynamically.
a.getClass().cast(bClass.newInstance);
but every time I get an Exception.
java.lang.ClassCastException
at java.lang.Class.cast(Unknown Source)
Can you tell me why?
Because, in your inheritance hierarchy, a B is not an A. You cannot cast one to the other.
Answer:
Because A is not extending B. (technicaly: A IS not B)
Explanation:
JVM performs "IS-A" test before it casts.
If "IS-A" test fails, you will get "ClassCastException".(Just like you are getting now).
IS-A :
IS-A test is to check whether a class(to be casted, in your case A) is in inheritance tree of the class(casted to, in your case B).
IS-A is the functional term, syntax to check IS-A test is instanceof".
e.g a instanceof b :
explanation of instance of:
LHS and RHS of the instance of must be the object.
thus a and b are obeject.
Their respective classes are checked for inheritance.
In your example following result will come.
a instanceof b : False
a instanceof basicObject : True
b instanceof a : False
b instanceof basicObject : True
basicObject instanceof a : False
basicObject instanceof b : False
You can only cast where result of instanceof is true.
Your hierarchy looks like this:
BasicClass
/ \
/ \
A B
A is not an ancestor of B, so it's impossible to cast an instance of B to A.
The output of the below snippet is 012, but kindly let me know how (b2 instanceof Toy) is getting true.
kindly explain on this.
interface Vessel { }
interface Toy { }
class Boat implements Vessel { }
class Speedboat extends Boat implements Toy { }
public class Tree {
public static void main(String[] args)
{
String s = "0";
Boat b = new Boat();
Boat b2 = new Speedboat();
Speedboat s2 = new Speedboat();
if((b instanceof Vessel) && (b2 instanceof Toy)) s += "1";
if((s2 instanceof Vessel) && (s2 instanceof Toy)) s += "2";
System.out.println(s);
}
}
You can assign an object to a variable of any type in its hierarchy, but instanceof will always examine the object itself when being evaluated. b2 references a Speedboat object, which implements Toy, hence b2 instanceof Toy is true.
I believe this post will help you understand clearly.
Taken from What is the 'instanceof' operator used for?
instanceof keyword is a binary operator used to test if an object
(instance) is a subtype of a given Type.
As the post explains, since Toy is implemented by SpeedBoat, the instanceof operator returns true for that condition.
Also the official oracle documentation of tutorial explains instanceof as:
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.
instanceof tests if the reference points to an object whose concrete type is, extends, or implements (directly or indirectly) the given type.
The object referenced by b2 is of type SpeedBoat. SpeedBoat implements Toy. So the object referenced by b2 is a Toy (i.e. is an instance of Toy).
instanceof is a synonym for "is a" in real life. If a child shows you a speed boat and asks "is that a toy", you'll answer yes. If he asks "is it a speed boat", you'll answer yes. If he asks "is it an object", you'll answer yes. If he asks "is it a banana", you'll answer no.
b2 is an instance of Speedboat, a class that implements Toy. As Speedboat extends Boat, it can be assigned to a type higher in the type hierarchy to it (Boat b2 = new Speedboat();), but as it is still an instance of Speedboat (try b2.getClass()), b2 instanceof Toy will still return true.
Be aware that instanceof should be used sparingly. If you find yourself writing code that uses instanceof, then investigate shifting the target code to a new member method in each subclass (which is usually where it belongs). In your code, both Boat and Speedboat could provide a method int getScore() that would remove the need for instanceOf.
One place that it is invaluable is in exception handling. For instance:
try {
.. Access the database
} catch (Exception ex) {
if (ex instanceof SQLException) {
.. Process the details of the database exception to log more detail
} else {
throw ex;
}
For example by the line
s2 instanceof Vessel
it is trying to find whether s2 is in the same hierarchy down the line of Vessel. Not necessarily direct relation but next to next or more distant relation would be answered true, if the 2 comparing class exist in same hierarchy. But instanceof will return false if they have no direct hierarchy.
Like
interface A{..}
interface B{..}
class C implements A {..}
then
C instanceof B
will return false
and
C instanceof A
will return true
(a instanceOf b) means the instanceOf operator returns true only if a belongs to the type of b..
Ex-If Dog is a super class and puppy is a sub class.then (Dog instanceOf puppy returns) true.
In your example its Vessel-->Boat-->speedBoat