kindly explain java instanceof keyword in this snippet - java

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

Related

instance Of Operator in java

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.

Accessing a randomly-assigned object

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!

instanceof throwing incompatible types

I recently came across a strange compilation error for my following code snippet :
class A {
}
class B extends A {
}
class Example {
}
class Demo {
public static void main (String args[]){
B b = new B();
if(b instanceof Example) {
System.out.println("Yes it is");
}
}
}
Now I am getting a compilation error on my predicate indicating that B and Example are incompatible operands. I searched for a while and found that the Eclipse environment shows such an error if the right hand operand is not imported. But in my case all the classes are in the same file. So I am unable to figure out the issue. Is it that instanceof only works for the hierarchies and the example I have been trying an invalid one?
b is defined as B, it can never be Example as there is no inheritance relationship between the two. You would rather do:
class Demo {
public static void main (String args[]){
A a = new B();
if(a instanceof B) {
System.out.println("Yes it is");
}
}
}
or if you insist on a type which can hold Example it would be:
class Demo {
public static void main (String args[]){
Object o = new Example();
if(o instanceof Example) {
System.out.println("Yes it is");
}
}
}
The compilier can and must check, if the type can be the given instance, see JLS 15.20.2
If a cast 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.
There is absolutely no way that the object referenced by b can be an instance of Example. This is known at compile time.
A reference of type B exists in this hierarchy
class B extends A {
}
while Example is in
class Example {}
There is no way a variable of type B can be referencing an object of type Example. For example, an instance of type B is already, obviously, not a subtype of Example. Furthermore, any subtype of B would be a subclass of B. Since Java doesn't support multiple inheritance, then it could not also be a subtype of Example. (The same could not be said if Example was an interface.)
The instanceof operator is used for runtime type checking. It would make sense, for example, to check if a reference of type A actually holds a B instance. However, Example and B are completely disjoint types - a reference to B can never hold an instance of type Example, therefore checking it is pointless, and can be failed at compile time.
instanceof is operator only work of inheritance and implementation . If object you are checking of is not from inheritance hierarchies then you will get compilation error . Do this below is the code
class Demo {
public static void main (String args[]){
A obj = new B();
if(obj instanceof B) {
System.out.println("Yes it is");
}
}
}
Here you cannot check obj instanceof Example , its wrong as is not from hierarchies.

How to convert a string to a type that implements an interface? [duplicate]

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);

How to test if one java class extends another at runtime?

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);

Categories