Accessing a randomly-assigned object - java

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!

Related

Unchecked cast from generic type to the same type

The following code generates a warning Unchecked cast: 'T' to 'U' in IntelliJ IDEA:
interface A {}
class B<T extends A, U extends A> {
void f() {
final T t = null;
final U u = (U) t;
}
}
This doesn't make sense to me, since T and U are defined as the same type. What is the problem?
T and U are not defined as the same type. They are both defined as extends A, which means T and U can be unrelated classes that implement the A interface. Hence the cast is not safe.
The only safe cast you can do is to cast references of type T or U to type A. Of course you don't need such a cast. You can simply assign them to a variable of type A.
While both T and U extend A, they are not the same type. Hence you cannot cast from one to the other.
Consider:
class D implements A {}
class E implements A {}
B<D, E> b;
You cannot cast from D to E.
Parent:
interface A {
}
Child:
class B implements A {
}
class C implements A {
}
In the above example A is parent B and C.
Example:
The below code will works fine.
A a = new B();
B b = (B)a;
This will trigger class Cast Exception.
B b = new B();
C c = (C) b;
You can't type cast with your Siblings type. This is because You may try to access the methods/properties that may present in the resultant class.
Same thing can be to String,Integer,Object. Object is parent
Integer & String are the child for Object class but you cannot cast these classed.
final T t = null;
final U u = (U) t;
Although this is unchecked, this is actually safe, because null can be cast to any reference type without a ClassCastException.
However, the compiler doesn't consider the value of a non-null reference when you cast it: it's simply "some" T. This is an example of where you, the programmer, know more about the types than the compiler, because you know that t == null, so you can legitimately ask the compiler to trust you by adding casts and #SuppressWarnings.
But if t were non-null, this wouldn't always be safe. T and U are different types: they are "something that extends A" and "something (maybe the same, maybe not) that extends A".
To make this a little bit more concrete, here's an equivalent example:
class B<T extends Serializable, U extends Serializable> {
U method(T t) {
return (U) t;
}
}
String s = new B<Integer, String>().method(1);
This will fail with a ClassCastException, because an Integer isn't a String.
If you don't want them to be different types, remove one of them (and, of course, the cast).

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.

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

kindly explain java instanceof keyword in this snippet

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

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