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.
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.
Upcasting is allowed in Java, however downcasting gives a compile error.
The compile error can be removed by adding a cast but would anyway break at the runtime.
In this case why Java allows downcasting if it cannot be executed at the runtime?
Is there any practical use for this concept?
public class demo {
public static void main(String a[]) {
B b = (B) new A(); // compiles with the cast,
// but runtime exception - java.lang.ClassCastException
}
}
class A {
public void draw() {
System.out.println("1");
}
public void draw1() {
System.out.println("2");
}
}
class B extends A {
public void draw() {
System.out.println("3");
}
public void draw2() {
System.out.println("4");
}
}
Downcasting is allowed when there is a possibility that it succeeds at run time:
Object o = getSomeObject(),
String s = (String) o; // this is allowed because o could reference a String
In some cases this will not succeed:
Object o = new Object();
String s = (String) o; // this will fail at runtime, because o doesn't reference a String
When a cast (such as this last one) fails at runtime a ClassCastException will be thrown.
In other cases it will work:
Object o = "a String";
String s = (String) o; // this will work, since o references a String
Note that some casts will be disallowed at compile time, because they will never succeed at all:
Integer i = getSomeInteger();
String s = (String) i; // the compiler will not allow this, since i can never reference a String.
Using your example, you could do:
public void doit(A a) {
if(a instanceof B) {
// needs to cast to B to access draw2 which isn't present in A
// note that this is probably not a good OO-design, but that would
// be out-of-scope for this discussion :)
((B)a).draw2();
}
a.draw();
}
I believe this applies to all statically typed languages:
String s = "some string";
Object o = s; // ok
String x = o; // gives compile-time error, o is not neccessarily a string
String x = (String)o; // ok compile-time, but might give a runtime exception if o is not infact a String
The typecast effectively says: assume this is a reference to the cast class and use it as such. Now, lets say o is really an Integer, assuming this is a String makes no sense and will give unexpected results, thus there needs to be a runtime check and an exception to notify the runtime environment that something is wrong.
In practical use, you can write code working on a more general class, but cast it to a subclass if you know what subclass it is and need to treat it as such. A typical example is overriding Object.equals(). Assume we have a class for Car:
#Override
boolean equals(Object o) {
if(!(o instanceof Car)) return false;
Car other = (Car)o;
// compare this to other and return
}
We can all see that the code you provided won't work at run time. That's because we know that the expression new A() can never be an object of type B.
But that's not how the compiler sees it. By the time the compiler is checking whether the cast is allowed, it just sees this:
variable_of_type_B = (B)expression_of_type_A;
And as others have demonstrated, that sort of cast is perfectly legal. The expression on the right could very well evaluate to an object of type B. The compiler sees that A and B have a subtype relation, so with the "expression" view of the code, the cast might work.
The compiler does not consider the special case when it knows exactly what object type expression_of_type_A will really have. It just sees the static type as A and considers the dynamic type could be A or any descendant of A, including B.
In this case why Java allows downcasting if it cannot be executed at the runtime?
I believe this is because there is no way for the compiler to know at compile-time if the cast will succeed or not. For your example, it's simple to see that the cast will fail, but there are other times where it is not so clear.
For instance, imagine that types B, C, and D all extend type A, and then a method public A getSomeA() returns an instance of either B, C or D depending on a randomly generated number. The compiler cannot know which exact run-time type will be returned by this method, so if you later cast the results to B, there is no way to know if the cast will succeed (or fail). Therefore the compiler has to assume casts will succeed.
# Original Poster - see inline comments.
public class demo
{
public static void main(String a[])
{
B b = (B) new A(); // compiles with the cast, but runtime exception - java.lang.ClassCastException
//- A subclass variable cannot hold a reference to a superclass variable. so, the above statement will not work.
//For downcast, what you need is a superclass ref containing a subclass object.
A superClassRef = new B();//just for the sake of illustration
B subClassRef = (B)superClassRef; // Valid downcast.
}
}
class A
{
public void draw()
{
System.out.println("1");
}
public void draw1()
{
System.out.println("2");
}
}
class B extends A
{
public void draw()
{
System.out.println("3");
}
public void draw2()
{
System.out.println("4");
}
}
Downcast works in the case when we are dealing with an upcasted object.
Upcasting:
int intValue = 10;
Object objValue = (Object) intvalue;
So now this objValue variable can always be downcasted to int because the object which was cast is an Integer,
int oldIntValue = (Integer) objValue;
// can be done
but because objValue is an Object it cannot be cast to String because int cannot be cast to String.
Downcasting is very useful in the following code snippet I use this all the time. Thus proving that downcasting is useful.
private static String printAll(LinkedList c)
{
Object arr[]=c.toArray();
String list_string="";
for(int i=0;i<c.size();i++)
{
String mn=(String)arr[i];
list_string+=(mn);
}
return list_string;
}
I store String in the Linked List.
When I retrieve the elements of Linked List, Objects are returned. To access the elements as Strings(or any other Class Objects), downcasting helps me.
Java allows us to compile downcast code trusting us that we are doing the wrong thing.
Still if humans make a mistake, it is caught at runtime.
Consider the below example
public class ClastingDemo {
/**
* #param args
*/
public static void main(String[] args) {
AOne obj = new Bone();
((Bone) obj).method2();
}
}
class AOne {
public void method1() {
System.out.println("this is superclass");
}
}
class Bone extends AOne {
public void method2() {
System.out.println("this is subclass");
}
}
here we create the object of subclass Bone and assigned it to super class AOne reference and now superclass reference does not know
about the method method2 in the subclass i.e Bone during compile time.therefore we need to downcast this reference of superclass to subclass reference so as the resultant reference can know about the presence of methods in the subclass i.e Bone
To do downcasting in Java, and avoid run-time exceptions, take a reference of the following code:
if (animal instanceof Dog) {
Dog dogObject = (Dog) animal;
}
Here, Animal is the parent class and Dog is the child class.
instanceof is a keyword that is used for checking if a reference variable is containing a given type of object reference or not.
Downcasting transformation of objects is not possible.
Only
DownCasting1 _downCasting1 = (DownCasting1)((DownCasting2)downCasting1);
is posible
class DownCasting0 {
public int qwe() {
System.out.println("DownCasting0");
return -0;
}
}
class DownCasting1 extends DownCasting0 {
public int qwe1() {
System.out.println("DownCasting1");
return -1;
}
}
class DownCasting2 extends DownCasting1 {
public int qwe2() {
System.out.println("DownCasting2");
return -2;
}
}
public class DownCasting {
public static void main(String[] args) {
try {
DownCasting0 downCasting0 = new DownCasting0();
DownCasting1 downCasting1 = new DownCasting1();
DownCasting2 downCasting2 = new DownCasting2();
DownCasting0 a1 = (DownCasting0) downCasting2;
a1.qwe(); //good
System.out.println(downCasting0 instanceof DownCasting2); //false
System.out.println(downCasting1 instanceof DownCasting2); //false
System.out.println(downCasting0 instanceof DownCasting1); //false
DownCasting2 _downCasting1= (DownCasting2)downCasting1; //good
DownCasting1 __downCasting1 = (DownCasting1)_downCasting1; //good
DownCasting2 a3 = (DownCasting2) downCasting0; // java.lang.ClassCastException
if(downCasting0 instanceof DownCasting2){ //false
DownCasting2 a2 = (DownCasting2) downCasting0;
a2.qwe(); //error
}
byte b1 = 127;
short b2 =32_767;
int b3 = 2_147_483_647;
// long _b4 = 9_223_372_036_854_775_807; //int large number max 2_147_483_647
long b4 = 9_223_372_036_854_775_807L;
// float _b5 = 3.4e+038; //double default
float b5 = 3.4e+038F; //Sufficient for storing 6 to 7 decimal digits
double b6 = 1.7e+038;
double b7 = 1.7e+038D; //Sufficient for storing 15 decimal digits
long c1 = b3;
int c2 = (int)b4;
//int 4 bytes Stores whole numbers from -2_147_483_648 to 2_147_483_647
//float 4 bytes Stores fractional numbers from 3.4e−038 to 3.4e+038. Sufficient for storing 6 to 7 decimal digits
float c3 = b3; //logic error
double c4 = b4; //logic error
} catch (Throwable e) {
e.printStackTrace();
}
}
}
I will tell you why this happened. First of all you have to understand how JVM supports when we assign parent class into the child class using downcasting, because of reference . For example consider in the following code.
A is the super type any class that extends from it and can store the reference B class.
A a =new B();
When you assign a reference variable into the child class jvm will understand that since A can store the reference of B class that is why you can do it.
B b=(B)b;
The reason which is called compile time error and why you couldn't directly assign Parent class into the Child class because there is not any extends relationship. Note that casting only occurring with the key which is called extends, that is why you receive the compile time error.
Another reason which is called ClassCastException by the runtime because of jvm it directly accept the rule which is okay I accept that it is true but jvm after that will understand that by the runtime it is not store any referance of Child class when code was writing by the programmer who write coding in the syntax .
I have the following codes:
1. public class Tester
2. {
3. public static void main(String[] args)
4. {
5. A a = new B();
6. System.out.println(a.getClass()); //Prints class B
7. System.out.println(a instanceof A); //Prints true
8. System.out.println(a instanceof B); //Prints true
9. System.out.println(a.valA); //Prints 1
10. System.out.println(a.valB); //Compilation error
11.
12. }
13. }
14.
15. class A
16. {
17. int valA=1;
18. }
19.
20. class B extends A
21. {
22. int valB=2;
23. }
At line 6 it shows that a is of type class B. However when it reaches line 10, the compiler produces an error: location: variable a of type A.
So my question is: What exactly is the class type of a now? Why getClass() shows that it is of type class B, yet the compiler complains it as type A during compilation?
Further more, since a instanceof B is true, why can't I access valB?
To make things clearer:
EDIT: I ran this statement: System.out.println(a); and the output was B#36d98810 which somehow proves that the toString() method of class B was executed. Since variable a can access the toString() method within class B, why can't it access valB which also resides in class B?
Professor Jonathan Shewchuk from UC Berkley explains about shadowing over here. Start at 18 minutes. (If the link changes just google search for CS 61B Lecture 15: More Java)
To answer your question in short there are two types for a variable, static type and dynamic type.
Static type is its Type at compile time
Dynamic type is its Type at run time.
In your example
A a = new B();
The static type of a is A and the dynamic type of a is B.
In Java a variable gets its non static methods from dynamic type
(if the method exists in both the parent and child class)
and
its fields and static methods from the static type.
This is true in C# only if the method is overridden in the sub class
Update:
The line
a instanceof A
tells you whether the dynamic type of a is of type A OR a subclass of A
Update 2:
AN example that illustrates this
public class PlayGround {
public static void main(String[] args) {
Animal a = new Dog();
System.out.print(a.name);// displays animal
System.out.print("\r\n");
a.MakeStaticSound();// displays static animal sound
System.out.print("\r\n");
a.MakeSound();// displays bow wow
}
}
class Animal {
public String name = "animal";
public void MakeSound() {
System.out.print("animal sound");
}
public static void MakeStaticSound() {
System.out.print("static animal sound");
}
}
class Dog extends Animal {
public String name = "dog";
public void MakeSound() {
System.out.print("bow wow");
}
public static void MakeStaticSound() {
System.out.print("static bow wow");
}
}
Please note that the more readable and preferred way to call a.MakeStaticSound() is Animal.MakeStaticSound()
a is not an object. It's a variable.
The type of the variable is A. The type of the object that the value of the variable refers to at execution time is B.
The compiler resolves everything against the compile-time type of the expressions involved - the variable in this case. When trying to resolve the name valB within the compile-time type of A, it fails to find anything - hence the error.
You need to keep in mind that compilation and execution are two different processes that happen at different times and have different kinds of information available to them. The compiler has to predict the future -- it has to decide whether it can guarantee that your code will make sense in the future, at runtime. It does this by analyzing the types of the objects in your code. The runtime, on the other hand, just has to inspect the current state of things.
When you read the line A a = new B(), you are inferring more information about the a local variable than the compiler is. The compiler basically just sees this as A a = <some expression>. It does not take note of the contents of the expression that's used to produce the value for a.
The fact that you've said A a = ... is you telling the compiler: "hey, this a thing I'm going to deal with in the rest of my program, it's just an A, don't assume anything more about it." If you had instead said B a = ..., then you're telling the compiler that it's a B (and the compiler also sees B extends A elsewhere in your code, so it knows it's also an A).
The subsequent expressions a instanceof A, a instanceof B, a.getClass(), and a.toString() are legal, from the compiler's point of view, regardless of the type of a: the instanceof operator and the getClass() and toString() methods are defined for all Objects. (The compiler does not need to predict what value those expressions will produce at runtime, just that they will produce either true or false, some Class<?>, and some String, respectively.)
But then when you come to a.valA and a.valB, the compiler actually has to do some real work. It needs to prove or guarantee that the a object will have a valA and a valB field at runtime. But since you've explicitly told it earlier to just assume that a is an A, it can not prove that it will have a valB field at runtime.
Now, later on, at execution time, the JVM has more information. When it evaluates a.getClass(), it actually looks up the concrete class that's "under the hood" of a and returns it. Similarly for instanceof B -- it looks up the concrete class and thus the result of that expression is true.
a.toString() works similarly. At runtime, the JVM knows that the thing referenced by a is actually a B, so it executes B's toString method.
This is a fundamental property of class inheritance, interfaces, etc.
Class "A" does not have a variable "valB".
If you want to use the variable "valB" in class "B" either, you should first cast Class "A" to "B"
Try :
System.out.println(((B)a).valB);
You should know the difference between object type and instance type. First is determined at compile type and at runtime it's doing the best to keep that type safe. Instance type is a class which object is instantiated.
A a; //this is an object type
new B(); //this is an instance type
A a = new B(); //all together, but a is of type A, having instance of type B.
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
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