为什么 ClassCastException 只会在运行时发生?

huangapple 未分类评论44阅读模式
英文:

Why ClassCastException only occur in Runtime?

问题

考虑以下代码

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

现在当你执行以下操作时

    b1=(B1)b;

即使很明显 b 不能转换为 B1代码仍然能够编译通过
那么为什么编译器在这里不报错呢

而是在运行时出现 ClassCastException编译器应该在这里更加智能才对
英文:

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.

答案1

得分: 0

这是按设计原则,也是动态/运行时多态性的核心概念。

通过编写 B b = new B();,你正在做两件事:

1- 告诉编译器 b 是指向类型 B 的引用。

2- 创建 B 类的实例并将其赋值给 b

在编译时,只有第一点被检查。实际存储的内容在运行时而不是编译时进行检查。 这就是运行时多态性的设计方式。我们可以在运行时将 b 分配给 BB1B2 的实例;

这有助于编写更易于维护和可扩展的代码。

在你的代码中,b1=(B1)b,编译器认为 b 可能具有 B1、B2 或 B 的对象,编译器故意跳过了在运行时进行此检查。如果你想避免运行时错误,你可以将代码编写在 if 块内,如下所示:

if (b instanceof B1){
   b1=(B1)b;
}
英文:

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

答案2

得分: 0

这里的 B 类是超类,可以引用子类(B1 类、B2 类)的对象。

B obj1 = new B1();

或者

B obj2 = new B2();

现在,如果你创建了一个引用类型为 B1 的对象,指向了父类 B 的对象,这将不起作用,除非你将 obj1 强制转换为父类类型,因为 B1 并不知道它指向了 B(父类)。

B1 b1 = obj1; // 错误
B1 b1 = (B)obj1; // 错误

现在在你的情况下,父类并没有指向子类的对象 B b = new B();,但是当你进行类型转换 b1=(B1)b; 时,它认为 b 可能指向子类,所以最初不会显示错误,但在编译时会显示错误。

英文:

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.

答案3

得分: 0

因为Java类是在运行时构建和实现的,所以它们与其他类和接口的关系也是在那时建立起来的。因此,Java将会在运行时注意到您与B1类相关的逻辑错误!
在编译时,JVM负责检查语法错误。JVM无法在编译时检测到像这样的一些错误,因为类及其与其他组件的关系尚未由Java编译器创建。
祝您好运。

英文:

(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

huangapple
  • 本文由 发表于 2020年7月25日 12:50:46
  • 转载请务必保留本文链接:https://java.coder-hub.com/63084480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定