[英]Error when runing the program, but not when compiling it
Why isn't there an error at line marked with //1 when you compile the program, but there is one when you run it. 为什么在编译程序时在标有// 1的行中没有错误,但是在运行程序时却有一个错误。 I am new to Java so I try to better understand how classes work.
我是Java的新手,所以我试图更好地了解类的工作原理。
class A{
private int x;
}
class B extends A{
private int a;
void exec(){
System.out.println("test");
}
static void function(A a){
((B)a).exec();//1
}
public static void main(String argv[]){
B.function(new A());
B.function(new B());
}
}
You say you get an error runnning the application, I am guessing the error in this case is ClassCastException
as A
is not a B
您说您在运行应用程序时遇到错误,我猜这种情况下的错误是
ClassCastException
因为A
不是B
Note this is a Runtime Exception : 注意,这是运行时异常:
see: https://docs.oracle.com/javase/7/docs/api/java/lang/ClassCastException.html 参见: https : //docs.oracle.com/javase/7/docs/api/java/lang/ClassCastException.html
Read more about Checked and UnChecked Exceptions here : 在此处阅读有关已检查和未检查异常的更多信息:
https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
http://beginnersbook.com/2013/04/java-checked-unchecked-exceptions-with-examples/ http://beginnersbook.com/2013/04/java-checked-unchecked-exceptions-with-examples/
The problem is that every B
is an A
(since B
extends A
), but the converse is not true: not every A
is a B
. 问题在于每个
B
都是A
(因为B
扩展了A
),但事实并非如此:不是每个A
都是B
Therefore, sometimes, you may be able to cast an A
to a B
as you did in your code above. 因此,有时,您可以像上面的代码一样将
A
转换为B
The compiler can however identify issues when there is a clear casting violation. 但是,当存在明显的转换冲突时,编译器可以识别问题。 For example, consider the case of trying to cast a
BufferedReader
to an Integer
: Since Integer
is not in the class hierarchy of BufferedReader
, the cast will fail with the error: 例如,考虑尝试将
BufferedReader
转换为Integer
:由于Integer
不在BufferedReader
的类层次结构中,因此强制转换将失败,并显示以下错误:
Cannot cast from Stage to Integer
无法从Stage转换为Integer
The reason you receive an exception only at runtime is that a ClassCastException
is a RuntimeException
. 仅在运行时收到异常的原因是
ClassCastException
是RuntimeException
。 Any exception that extends RuntimeException
is not checked at compile time. 扩展
RuntimeException
任何异常都不会在编译时检查 。 From the JavaDoc for Exception
: 从JavaDoc中获取
Exception
:
The class
Exception
and any subclasses that are not also subclasses ofRuntimeException
are checked exceptions.Exception
类和不是RuntimeException
子类的任何子类都是已检查的异常。 Checked exceptions need to be declared in a method or constructor's throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary.如果检查的异常可以由方法或构造函数的执行抛出,并在方法或构造函数的边界外传播,则需要在方法或构造函数的throws子句中声明它们。
Basically, Java allows you to cast a reference type to another reference type if it is possible that the cast will succeed, ie it's possible that it won't throw a ClassCastException
. 基本上,Java允许您在转换成功的情况下将引用类型转换为另一个引用类型,即,它可能不会抛出
ClassCastException
。 It can't guarantee that it will succeed, of course, because as you've seen, a reference to an A
could be referring to a B
object, but it might not be a B
object. 当然,它不能保证它会成功,因为正如您所看到的,对
A
的引用可能是对B
对象的引用,但它可能不是B
对象。
Section 5.5.1 of the JLS elaborates on what causes the compiler error if both the original reference type (S) and the casting type (T) are class types: 如果原始引用类型(S)和转换类型(T)都是类类型,则JLS的5.5.1节详细说明了导致编译器错误的原因:
Given a compile-time reference type S (source) and a compile-time reference type T (target), a casting conversion exists from S to T if no compile-time errors occur due to the following rules.
给定编译时参考类型S(源)和编译时参考类型T(目标),如果由于以下规则而没有发生编译时错误,则存在从S到T的转换转换。
If S is a class type:
如果S是类类型:
- If T is a class type, then either |S|
如果T是类类型,那么| S | <: |T|, or |T|
<:| T |或| T | <: |S|.
<:| S |。 Otherwise, a compile-time error occurs.
否则,将发生编译时错误。
(The notation <:
in the JLS means "is a subtype of".) (JLS中的符号
<:
表示“是”的子类型。)
Because B
is a subtype of A
, your cast of a A
to a B
is legal, because it is possible for it to succeed. 由于
B
是的子类型A
,你的一个铸造A
到B
是合法的,因为有可能是成功的。 By contrast, casting to an unrelated type, eg String
, will generate a compiler error; 相反,强制转换为不相关的类型(例如
String
)将产生编译器错误; that cast cannot succeed. 那种铸造不能成功。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.