异常而不是编译器错误

时间:2013-08-22 07:38:42

标签: java

我希望这个程序能给我编译错误,但编译成功,运行时遇到运行时异常。

class substr11
{

public static void main(String args[])
{

String s = "abcde";

System.out.println(s.substring(1,-1));

}


}

编译器错误应该能够解析(字符串在正文本身中初始化),并发现这个字符串操作会导致编译错误吗? 有人能告诉我为什么它没有抛出编译错误吗?

线程“main”中的异常java.lang.StringIndexOutOfBoundsException:String ind 超出范围:-2         at java.lang.String.substring(Unknown Source)         在substr11.main(substr11.java:9)

7 个答案:

答案 0 :(得分:3)

编译错误是指编译器无法编译代码时(语法错误,缺少符号等)。

在您的计划中情况并非如此,您按预期将int传递给String#substring,并且您没有遗漏任何内容(没有丢失的类,括号可以,分号是假设,为什么编译器要关心?

如果代码已编译,但由于某些异常(如ArrayIndexOutOfBounds)而崩溃,则会出现例外

答案 1 :(得分:1)

编译器从不解析或优化方法调用。尽管子字符串操作可能无效并且具有硬连线参数,但它并不重要,因为它不会解析整个方法调用。

该调用可能会产生副作用,或者仅在复杂的条件集中抛出运行时异常,这些条件可能包括实例,静态变量甚至库的选择。

编译错误可能包含无效语法,但不包括这样的内容。方法调用有效。也许某个字符串可以为其子字符串方法获取这组参数。编译器不会对该字符串执行复杂的分析。

如果这样做,编译将永远存在,并且会出现许多错误。

答案 2 :(得分:1)

代码中没有编译时错误。对substring()的调用需要两个int,这是对substring method的有效调用。

编译器不检查String内容,因此它没有看到这会在运行时抛出异常。

就编译器而言,s变量仅假设为String,其内容没有假设。在这种情况下,它已被赋予一个常量值,但它可能是一些无法估量的东西,例如数据库查询结果或其他任何东西。这同样适用于函数的int参数。

总结一下,正如他的回答中指出的六分法,编译器并没有对输入进行复杂的分析。开发人员负责对输入进行必要的检查,以避免运行时或检查异常,或者相应地捕获它们。

答案 3 :(得分:1)

编译器不知道操作的结果是什么。他知道s.substring()需要2个int参数,并且他确保调用是正确的(s.substring(1,-1)必须使用int参数)。

答案 4 :(得分:0)

花些时间阅读Spec JLS#11.2

  

编译时检查例外

     

Java编程语言要求程序包含检查异常的处理程序,这些异常可能是由于执行方法或构造函数而导致的。对于每个可能结果的已检查异常,方法(第8.4.6节)或构造函数(第8.8.5节)的throws子句必须提及该异常的类或该异常类的一个超类(§ 11.2.3)。

     

此异常处理程序存在的编译时检查旨在减少未正确处理的异常数。 throws子句中命名的已检查异常类(第11.1.1节)是方法或构造函数的实现者和用户之间的契约的一部分。重写方法的throws子句可能没有指定此方法将导致抛出任何被抛出的方法不允许被抛出的方法抛出的任何已检查异常(§8.4.8.3)。

异常hirarchy

java.lang.Object
  java.lang.Throwable
    java.lang.Exception
     java.lang.RuntimeException
       java.lang.IndexOutOfBoundsException
         java.lang.StringIndexOutOfBoundsException

异常发生在运行时而非编译时。

答案 5 :(得分:0)

不要混淆编译器作业,简而言之就是将代码转换为低级指令,以及代码执行。在你的情况下,程序应该调用很多子函数来“理解”代码中存在逻辑错误。

答案 6 :(得分:0)

  

有人可以告诉我为什么它没有抛出编译错误吗?

因为它不是编译错误,并且Java程序员(及其管理员!)有权依赖而不是编译错误!!

在另一个世界中,Java语言可能已被指定为要求(或允许)编译器尝试评估该substring调用,并将其标记为错误。

但是,在这个世界中,Java编译器只允许允许为“常量表达式”执行此操作(如JLS 15.28中所述)。根据规范,任何包含方法调用的表达式都不是“常量表达式”。因此,实际上,substring调用必须在运行时进行评估,并且必须为您提供运行时异常。


那么为什么Java会这样设计呢?

你需要问Java设计师......

...但我认为这是两件事的组合:

  • Java 1.0语言必须尽早发布,否则会错失市场机会。

  • 然后对向后兼容性有了全面的要求......因此旧的Java程序将随着语言的发展而继续发挥作用。