简体   繁体   English

运行程序时出错,但编译时不出错

[英]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 . 仅在运行时收到异常的原因是ClassCastExceptionRuntimeException 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 of RuntimeException 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 ,你的一个铸造AB是合法的,因为有可能是成功的。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM