0

Considering following code.

class B {}
class B1 extends B {}
class B2 extends B {}
public class ExtendsTest{
    public static void main(String args[]){
        B b = new B();
        B1 b1 = new B1();
        B2 b2 = new B2();

    }
}

Now when you do

b1=(B1)b;

It still compiles even it is obvious that b cannot be case to B1. So why compiler does not give error here.

Instead ClassCastException appears at runtime. Compiler should be more intelligent here.

Marcela28
  • 17
  • 1
  • 5
  • This comes under unchecked exception.Unchecked are the exceptions that are not checked at compiled time. It is not forced by the compiler to either handle or specify the exception. – Harmandeep Singh Kalsi Jul 25 '20 at 04:55
  • Refer to this doc for clarification : https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html – Amit kumar Jul 25 '20 at 05:02
  • ok thanks . But when you do b2=(B2)b1; it right away gives me compile error – Marcela28 Jul 25 '20 at 05:04
  • @Marcela28, Its because b1's type is B1 and b2's type is B2. B1 & B2 are different types. But both b1&b2 are also of type B. Please refer the my answer below to you question. Hope your doubt will be cleared. – Dexter Jul 25 '20 at 05:23
  • 1
    Since the variable `b` is of type `B`, it can store an instance of the subclass `B1` or `B2`. If the variable `b` is assigned to `new B1()`, `b1 = (B1)b` can be executed without any problems. So the compiler cannot error out `b1 = (B1)b`. –  Jul 25 '20 at 05:53

3 Answers3

0

This is by design and it is the core concept of dynamic/runtime polymorphism.

By writing B b = new B();, you are doing two things:

1- Instructing compiler that b is a reference to type B.

2- Creating an instance of B and assigning it to b.

At compile time, only point-1 is checked. What is actually stored- is checked at run time not at compile time. This is how run time polymorphism is designed. we can assign, instance of B, B1 or B2 at runtime to b;

This help in writing better maintainable & extendable code.

In your code b1=(B1)b, Compiler thinks b may be having object of B1, B2 or B. Compiler knowingly skip this to be checked at runtime. If you want to avoid the runtime error, you can write your code inside if block like:

if (b instanceof B1){
   b1=(B1)b;
}
Dexter
  • 4,036
  • 3
  • 47
  • 55
0

Here Class B is the superclass, which can be referenced to object of subclasses (class B1, class B2)

B obj1 = new B1();

OR

  B obj2 = new B2();

now if you create object of reference type B1 pointing to object of B (parent class), This will not not work until and unless you cast obj1 with parent class, because b1 B1 does not know that the parent class (B) it pointing to B1.

B1 b1 = obj1; //error
B1 b1 = (B)obj1; //error

Now in your case the parent class is not pointing to child class B b = new B();, but as you cast b1=(B1)b; it thinks that b might be pointing to the child class so it does not show any error initially but when compiled it shows error.

Shiv Patel
  • 114
  • 7
  • thanks. But compiler should be more clever. It is right in the code that b is pointing to Base class and not to child class. So it would be possible for compiler to check this, but instead it is at runtime. But ok. – Marcela28 Jul 25 '20 at 06:02
0

(I'm not entirely sure what I said, but I think it makes sense)

Because Java classes are built and implemented at runtime, their relationships with other classes and interfaces are then established. Therefore, Java will notice your logical error in relation to class B1 at runtime! The JVM is responsible for checking syntax errors during Compile-time. The JVM could not detect some errors like this at compile time because the class and its relationships to other components were not yet created by the Java compiler. Good luck

BLACK SOUL
  • 11
  • 3