don*_*ote 2 php exception-handling exception try-catch
考虑以下代码。
class C {}
/**
* @throws \InvalidArgumentException
*/
function classCreateInstance($class) {
if (!is_string($class)) {
throw new \InvalidArgumentException("Class name must be a string.");
}
if (!class_exists($class)) {
throw new \InvalidArgumentException("Class '$class' does not exist.");
}
return new $class();
}
/**
* @return C
*/
function foo() {
return classCreateInstance(C::class);
}
Run Code Online (Sandbox Code Playgroud)
有一个函数可能会抛出异常,因为它对$class
参数一无所知。
另一方面,调用代码知道“C”是一个有效的类名,因此它会假设“InvalidArgumentException”永远不会发生。它希望避免冗长的 try/catch,并且希望避免拥有自己的@throws
标签。特别是如果它不被“允许”拥有一个,因为它正在实现一个不注释异常的接口。
但是,从 IDE/自动代码验证的角度来看,忽略此异常是不安全的。
那么..从调用代码的角度处理“几乎不可能”的异常的正确方法是什么?
在爪哇。“已检查”异常类和“未检查”异常类之间存在区别。只有经过检查的异常是接口契约的一部分,而即使接口没有声明它,也允许抛出“未经检查的”异常。
在 Java 中,在“不应该发生”的情况下,会抛出未经检查的异常 - 例如“RuntimeException”。
在 PHP 中,这都是基于约定的。方法可以抛出它们想要的任何异常。@throws
在文档注释中添加标签很好,但它不是由语言强制执行的。
但是,可以将 IDE 或其他可能的代码审查工具配置为基于已检查与未检查异常的 Java 模型来分析代码。
例如,PhpStorm 可以选择不需要@throws
RuntimeException 和 LogicException的doc 标记。因此,这将允许将这些视为“未检查”,然后编写自定义异常类并将它们视为 Java 中的“已检查”异常。
PHP 中的原生异常类:http :
//php.net/manual/en/spl.exceptions.php#spl.exceptions.tree 并不是说这些都继承自 LogicException 或 RuntimeException,因此它们都将被视为“未检查”。只有根类Exception
(和自定义子类)会被视为“已检查”。
这种区别还意味着,如果您调用一个没有声明/注释异常的方法/函数,您仍然需要考虑可能会抛出异常。例如,这可以通过应用程序顶层的 try/catch 来覆盖。(例如一个 index.php)