在一个在线论坛上,有人提到 Java 的静态异常检查不是很好,并且会导致可伸缩性和版本控制问题。
我认为类函数的变化会引发新的异常,破坏客户端代码可以归因于版本控制问题。但我不确定。
静态异常检查的可扩展性问题是什么?
什么是动态异常检查?
在一个在线论坛上,有人提到 Java 的静态异常检查不是很好,并且会导致可伸缩性和版本控制问题。
我认为类函数的变化会引发新的异常,破坏客户端代码可以归因于版本控制问题。但我不确定。
静态异常检查的可扩展性问题是什么?
什么是动态异常检查?
当程序员未能抛出适合该方法的异常时,Java 中的已检查异常可能会导致可伸缩性问题。(参见Effective Java,第 43 条:抛出适合抽象的异常)。
懒惰的程序员倾向于将异常附加到throws
他们方法的子句中,而不考虑它们是否合适。因此,当您在应用程序架构中看起来越来越高时,方法会收集越来越多的异常。如果一个不小心,顶级方法可能会抛出十个或更多异常。
例如,在设计用于加密数据的方法中,可能会抛出许多低级异常(例如IOException
,NoSuchAlgorithmException
... KeyNotFoundException
)。没有必要将这些公开给 API 用户。相反,EncryptionFailed
可能会引发异常,并将血淋淋的细节存储在cause
异常的字段中。
我认为“动态异常检查”可能是指捕获Throwable
或Exception
(根类之一)并根据某些外部刺激动态决定是否处理异常。例如:
List<Class<?>> exceptionTypes = new ArrayList<>();
exceptionTypes.add(IllegalArgumentException.class);
exceptionTypes.add(IOException.class);
try {
// do something
} catch (Exception e) {
if (exceptionTypes.contains(e.getClass())) {
e.printStackTrace();
}
}
注意:上面的例子只是一个例子。但是想象一个代表用户执行代码并允许他们选择他们希望捕获的异常类的 IDE。
我想动态异常检查只是在运行时触发异常的另一个名称。
虽然我相信静态异常检查,但 Java 的静态异常检查方式确实存在涉及接口实现的问题。
说,我们有IParser
。parse()
它的方法可能会抛出哪些适当的异常?可能SyntaxErrorException
。现在我们希望 aServerResponseParserFromURL
以这样的方式使用:
class ServerResponseParserFromURL implements IParser { .... };
....
try {
IParser parser = new ServerResponseParser(new URL("http://example.com/test.htm"));
parser.parse();
....
}
这就是问题所在——IParser
可能会触发的实现,例如NoRouteToHostException
. 所以我们不能使用漂亮简洁的形式,需要回退到长形式:
class ServerResponseParser implements IParser { .... };
....
try {
String response = getServerResponse(new URL("http://example.com/test.htm"));
IParser parser = new ServerResponseParser(response);
parser.parse();
....
}
如您所见,在实践中,我们的IParser
is IStringParser
,而不是 generic IParser
。
尽管在这种特殊情况下它可能是可以容忍的,但是当我们想要提供一个IParser
作为函数的参数之一时它会使事情变得复杂f
。比如说,为了能够解析 url 识别的服务器的响应,我们不能只提供ServerResponseParser
对象和 url——我们需要找到一种方法来提供getServerResponse
方法到f
.