PHP 为什么只能用 throw 才能 catch 异常

2016-11-18 15:09:32 +08:00
 gps32251070

之前对抛出的作用的理解是,是逻辑处理层和异常处理层分离。如果不是这样,那么直接用 if...else 语句或者自己写一个不用继承 Exception 的类都可以达到目的了(比如记录日志)。

但是 php 中异常要 throw 才能 catch ,但是 throw 的时候感觉避免不了 if...else ,这样感觉这个 throw 有点多余啊?还是我的理解有问题 ?

比如这两种,有什么区别?

try {
	if (...) {
    	throw new Exception();
    }
} catch (Exception $e) {
	...
}
if (...) {
	MyException::log() // 记录或者处理
}

如果不用 throw 就确实能把逻辑处理层和异常处理分离开

try {
	...
} catch (AException $e) {
	...
} catch (BException $e) {
	...
} ...
7006 次点击
所在节点    PHP
16 条回复
sweb
2016-11-18 15:21:30 +08:00
你理解有问题,我肯定,至少看着我都觉得你混乱。所谓的 throw 就是触发异常,这个 php 没有啥特别之处。
irgil
2016-11-18 15:26:23 +08:00
try {
if (...) {
throw new Exception();
}
} catch (Exception $e) {
...
}
if (...) {
MyException::log() // 记录或者处理
}

区别在于第一种你不需要立即处理异常。这个 php 没关系...
gps32251070
2016-11-18 15:26:37 +08:00
@sweb 哈哈,可能我表达的有些混乱吧,我的意思就是为什么不能自己主动抛出异常,比如在内核层次 throw
gps32251070
2016-11-18 15:28:30 +08:00
@irgil 贴这两段代码的意思是为什么不能自动 throw ,这样是有什么好处么?
wizardoz
2016-11-18 15:39:55 +08:00
虽然我不懂 PHP 但是异常当然要 throw 才能 catch.
一些语言看似自动抛出异常,但是我觉得应该理解为特定的异常在标准库中为你 throw 了,比如 IO 接口的异常,因为用户代码接触不到 IO 接口的状态,所以 IO 接口的异常由 IO 标准库 throw.
但是用户自定义的异常,自然用户自己 throw.

另外,我认为异常处理不是为了避免 if...else...,而是为了减少多层次的使用 if else.
假设 d 库调用 c 库,c 库调用 b 库,b 库调用 a 库.如果没有异常处理的话,a 库,b 库,c 库和 d 库都要用 if 判断状态是否正确.但是有了异常处理,可以谁都不用判断状态,只要 a 库 throw 异常,用户代码 catch 异常就可以了.
irgil
2016-11-18 16:02:26 +08:00
@wizardoz 运行时异常一般都是自己抛的,楼主显然不了解 throw 是干嘛的。。
ZiLong
2016-11-18 16:12:15 +08:00
@gps32251070 以 javaer 观之,是否是受检异常和非受检异常的问题(受检异常被认为是不好的设计,所以 C#抛弃了受检异常的设计
enenaaa
2016-11-18 16:14:51 +08:00
异常机制初衷就是自行触发来转移程序流程, 解决逻辑嵌套太深时错误处理的困难。
标准库触发的异常只是补充啊。至于 php 的 catch 不捕获系统异常。
https://secure.php.net/manual/en/language.exceptions.php
Note:

Internal PHP functions mainly use Error reporting, only modern Object oriented extensions use exceptions. However, errors can be simply translated to exceptions with ErrorException.

看起来是历史原因。
gps32251070
2016-11-18 16:20:41 +08:00
@enenaaa 所以即能自动抛出系统异常,也能自定义是最好的
irgil
2016-11-18 16:22:26 +08:00
@ZiLong 我还以为除了 java 别的语言也是这么干的。。。无知了
iyaozhen
2016-11-18 16:52:10 +08:00
@ZiLong 涨姿势了,原来是这种思路的区别。

自动捕获异常可能比较方便,但容易麻痹大意。我看现在好多 java 代码都是一个 try catch 到底,异常捕获没有细分

PHP 一般用不上异常捕获,因为 cgi 的运行模型,一次请求挂了就挂了不会影响其它服务。不过开发大的系统还是要做异常处理。现在 php 做常驻进程的也有很多。( php7 的异常捕获能捕获系统异常了)
jhdxr
2016-11-18 17:55:21 +08:00
@enenaaa @gps32251070 然而 PHP 7 changes how most errors are reported by PHP. Instead of reporting errors through the traditional error reporting mechanism used by PHP 5, most errors are now reported by throwing Error exceptions. https://secure.php.net/manual/en/language.errors.php7.php
gps32251070
2016-11-18 17:58:51 +08:00
@jhdxr 很好,这很 PHP7
cxbig
2016-11-18 22:08:21 +08:00
如果有一个异常是你主动抛出来的,当然可以用 if else 结构来简化。

但是很多情况是:在你的逻辑里只是把参数丢给其他类来处理, Exception 在处理过程中由其他的类抛出来,这时你必须要用 try catch 来抓了
lianxiaoyi
2016-11-19 17:03:40 +08:00
难道 java 不需要先 if?????我收到一个参数 a=1 然后我有一个判断 a 必须大于 3 , java 难道不用判断就知道收到 1 不对然后抛个异常????
ZiLong
2016-11-21 10:36:01 +08:00
@irgil 其他语言也是一步步进化过来的,C#也是在 3.0(没记错的话)后去掉的受检异常,还有下面 @jhdxr 说的 PHP7 也是去掉了受检异常,只是 java 进化非常缓慢,有种说法是 C#3.0 约等于 Java 8.0.Java 还是生态好~~Android,大数据,,,,

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/321506

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX