Exception 设计带有已检查异常的语言

Exception 设计带有已检查异常的语言,exception,language-design,Exception,Language Design,我很清楚关于检查异常是否是一个好主意的整个争论,我站在他们一边……但这不是这个问题的重点。我正在设计一种相当简单的编译OOP语言,我决定使用检查异常基本上作为返回错误的一种方式,而不必沿着返回错误代码的C路线 我想了解一下如何改进检查异常的Java模型,以消除它们的大部分不好的方面,可能是语法上的更改或实际功能的轻微更改。对检查异常的一个主要批评是,懒惰的程序员可能会吞下它们,因此不会出现错误 也许捕捉异常是可选的,因此如果没有捕捉到异常,程序会崩溃?或者可能有特定的符号来表示一个异常没有被处理

我很清楚关于检查异常是否是一个好主意的整个争论,我站在他们一边……但这不是这个问题的重点。我正在设计一种相当简单的编译OOP语言,我决定使用检查异常基本上作为返回错误的一种方式,而不必沿着返回错误代码的C路线

我想了解一下如何改进检查异常的Java模型,以消除它们的大部分不好的方面,可能是语法上的更改或实际功能的轻微更改。对检查异常的一个主要批评是,懒惰的程序员可能会吞下它们,因此不会出现错误

也许捕捉异常是可选的,因此如果没有捕捉到异常,程序会崩溃?或者可能有特定的符号来表示一个异常没有被处理(像C++虚拟函数’=0’符号)。或者,如果异常处理程序为空,我甚至可能导致程序崩溃(尽管这可能会让不熟悉该语言的程序员感到惊讶)


关于try…catch语法,您认为有没有更简洁的方式来表示正在捕获异常?该语言将使用垃圾收集器,与Java非常相似,因此是否需要finally子句?最后,检查过的异常还有哪些其他缺点,以及存在哪些潜在的解决方案(如果有的话)?

我看不到另一种方法来绑定可能出现错误的代码块。我认为这是一种尝试。。捕捉块是一致的。Ruby,作为一种改进,有一个关键字,它允许重复代码的失败,这是一个很好的改进,我认为

< P>我认为你应该在JDK7中读Neil Gafters,以及在C语言(vs. java)中的异常处理< /P> < P>我认为你应该考虑使用三态单元格,如Load box类型来处理错误。那么您就根本不需要使用异常了

我很清楚关于检查异常是否是一个好主意的整个争论,我认为它们是

FWIW,我同意——总的来说,它们是一件好事(tm)。程序员在使用特性时的坏习惯并不一定意味着特性是坏的。在大多数情况下,我认为程序员不明白他们可以忽略异常并将其推上链

也许捕捉异常是可选的,因此如果没有捕捉到异常,程序会崩溃

Java有这个特性(
RuntimeException
,它的子类是未检查的异常)

或者可能有特定的符号表示未处理异常

爪哇有这一点;
在方法声明中抛出
子句

关于try…catch语法,您认为有没有更简洁的方式来表示正在捕获异常

当然,它可能感觉有点笨拙,但目标是将异常条件从主线逻辑中排除

不过,我确实有几点建议供您参考。
try..catch

catch..from
这是我在Java和相关语言中很长一段时间以来一直想要的东西(真的需要正确编写并提交JSR):
catch…from

下面是一个例子:

FileOutputStream    output;
Socket              socket;
InputStream         input;
byte[]              buffer;
int                 count;

// Not shown: Opening the input and output, allocating the buffer,
// getting the socket's input stream

try
{
    while (/* ... */)
    {
        count = input.read(buffer, 0, buffer.length);
        output.write(buffer, 0, count);

        // ...
    }
}
catch (IOException ioe from input)
{
    // Handle the error reading the socket
}
catch (IOException ioe from output)
{
    // Handle the error writing to the file
}
如您所见,这里的目标是分离套接字读取错误和文件写入错误的无关错误处理。这是一个非常基本的想法,但其中有很多微妙之处。例如,套接字或文件输出流实例所使用的其他对象抛出的异常需要像该实例抛出的异常一样进行处理(不太难,只需要确保实例信息在堆栈跟踪中)

这可以通过现有的机制和严格的编码准则来实现,但这是非常困难的

单个块中的多个catch表达式 计划中的JDK7增强

重试 非常非常难提供比上面更难的,也更容易为人们工作,所以价值要低得多。但是:提供“重试”语义:

try
{
    // ...stuff here...

    if (condition)
    {
        foo.doSomething();
    }

    // ...stuff here...
}
catch (SomeException se)
{
    if (foo.takeRemedialAction() == Remedy.SUCCESS)
    {
        retry;
    }

    // ...handle exception normally...
}
在这里,
doSomething
可能以异常方式失败,但以
takeRemedialAction
可能能够纠正的方式失败。这延续了将例外情况排除在逻辑主线之外的主题。当然,
retry
会将执行返回到失败的操作,该操作可能深入到
doSomething
或它调用的某个子方法中。你明白我说的挑战是什么意思


对于团队来说,使用现有机制更容易做到这一点:只需将
doSomething
加上
takeremedialaaction
的子例程设置为异常,并将该调用放在主线逻辑中即可。所以,这一个在列表中的位置很低,但是嘿…

检查异常只是一个更普遍的驱动力的小例子,Erik Meijer称之为类型诚实。也就是说,程序、方法、功能不应与其类型有关。如果您看到一个类型签名,您应该能够信任它的类型

对于今天的Java来说,情况并非如此(特别是如果您想象一个Java——没有经过检查的异常)

如果您在Java中有这样的类型签名:

Foo bar(Baz)
它说“我把一个
Baz
作为输入,产生一个
Foo
作为输出”。但那是谎言

实际上,
bar
Baz
null
作为输入。它还将整个全局状态、类状态和实例状态以及整个宇宙作为输入(通过文件I/O、网络I/O、数据库I/O等)。并且它也不产生
Baz
作为输出:它产生
Foo
null
或异常或
底部
(即完全没有)。另外,它的输出还包括整个全局状态,即enti
(IO<Foo | null | Exception> | Bottom) bar(IO<Baz | null>)
String fileReader(String filename) {
  return this.fileHelper.read(filename);
}
String fileReader(String filename) throws IOException, CustomFileReaderEx
String fileReader(String filename) throws InvalidFilenameEx, CorruptDataEx
String fileReader(String filename) throws like this.fileHelper.read
Foo whatever() throws like fileReader
String fileReader(String filename) throws like FileHelper.read