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.
Related
There is the following code:
class A {}
class B extends A {}
#Test
public void test4() {
A a = new A();
B b = new B();
Class<? extends A> aClass = a.getClass();
Class<? extends B> bClass = b.getClass();
System.out.println(aClass == bClass);// #1 false
System.out.println(aClass == A.class);// #2 true
System.out.println(aClass == B.class);// #3 false
System.out.println(bClass == A.class);// #4 error:java: non comparable type: java.lang.Class<capture#1, ? extends Test.B> and java.lang.Class<Test.A>
System.out.println(bClass == B.class);// #5 true
}
As shown above, I am very confused about this error. Because in my opinion, a.getClass() and A.class are the same object, and the values of these two variables are indeed the same when I debug. Then I think #3 and #4 are equivalent, there should be no error. I feel like it might be some cause of type erasure, but I don't know much about it.
Does anyone know what could be the reason for this?
This is a bit like wondering why you can write
String s = "hi";
Integer i = 42;
Object so = s;
Object io = i;
System.out.println(so == io); // compiles, prints false
System.out.println(s == i); // compilation error: String and Integer are incomparable types
in spite of so and s referring to the same object. Well, it's because the compiler is checking types, not objects. It's obvious nonsense to compare a String and Integer with ==. It's less obvious nonsense to compare two Object with ==.
So let's look at the types:
aClass == B.class
asks whether some subclass of A is in fact B. Since B is a subclass of A, that's quite possible. For instance, the following program will print true:
A a = new B();
Class<? extends A> aClass = a.getClass();
System.out.println(aClass == B.class);
(the ability to put a B into a variable declared with type A is precisely why getClass() returns Class<? extends A> rather than Class<A>)
On the other hand
bClass == A.class
doesn't make sense. It asks whether bClass, which is some subclass of B, is A. It that were true, A would be subclass of B, which is declared to be a subclass of A, so A and B would be subclasses of each other! That's impossible!
I have the following
Class A extends B
B class is an abstract class
What will be returned if I do:
A a = new A();
a instance of B?
If it returns false, which solution I could use for having true as result?
//Define these classes.
class A {} //It can be an abstract class as well.
class B extends A {}
//Main code.
A b = new B();
System.out.println(b instanceof A); //prints true.
If you try B instanceof A // you will get a compilation error because B is not an object, but it is a class name.
"x instanceof y" returns true if "object" x is instance of class "y". The word instance is used for an object. Since A and B are both classes the code should return a compilation error
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.
Please tell me why i am getting ClassCastException in this case
I have type casted , the source of B class to A as shown below , but why i am still getting ClassCastException here .
public class A extends B
{
}
public class B {
public String getData() {
return "B";
}
}
public class Main {
public static void main(String args[]) {
A a = new A();
B b = new B();
a = (A) b;
System.out.println(a.getData());
}
}
It becomes more obvious if we play with different classnames:
public class Car extends SomethingWithWheels {} // was A extends B
public class SomethingWithWheels {} // was B
public class Train extends SomethingWithWheels {} // aahh, some C extends B
Now, lets cast again:
SomethingWithWheels somethingWithWheels = getItFromSomewhere();
Car car = (Car) somethingWithWheels;
The compiler has to complain, because somethingWithWheels (B) could be a Train instance (C), which can't be cast to Car (A).
You can't cast a base class to derived class. You can do the other way round though.
Because your instance "b" is not of type A (B does not extend A), so when you cast "b" to A it fails.
The opposite would work (casting an instance of type A to type B)
Because an instance of B is not an instance of A. It's really that simple.
If you create an instance of A, it's also a B - because that's what the subclassing means. However, if you create an instance of B, that is not an A, and can't be assigned/cast as such.
The only time you can cast is if the run-time class of an object is compatible with the type you're trying to cast to. You can't change the class of an existing object - which is what I think you might be trying to do here - only tell the compiler "look, I know it's really something more specific".
So as a counter-example, the following would work:
public static void main(String args[]) {
B b = new A();
A a = (A) b;
System.out.println(a.getData());
}
In this case, the variable b is declared to hold a reference to a B. It turns out that you populate it with an instance of A, but for the rest of the program the compiler isn't allowed to assume that b is an A, because it's not guaranteed. Since you know it's an A in your specific case, you insert the cast, which causes a run-time check that the object actually is an A. This succeeds, and from that point on you can call methods specific to A on your a variable.
In this case however there is no reason at all to do any casting - there are no extra methods available on the subclass that you'd need to call, and no methods which only take an A but not a B. Even if A overrode getData to do something different, you would still get this behaviour if invoking through a B reference.
You are downcasting and you try to cast a supertype to a subtype, thats why it does well during compilation but fails at runtime with ClassCastException.
You can call:
System.out.println(a.getData());
after removing the line where you try to cast the types
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);