异常(exception)和执行失败有什么区别?
例如一个User Class 的 add 方法,在成功的情况下返回用户对象实例,在失败的情况返回False并可以通过getError方法获取失败原因字符串........
说到这里,我好像明白了,难道add方法总是应该返回用户对象,否则抛出异常吗?
但是这样的话,他们的代码量没什么区别的啊。问题在于即使调用add方法处没有捕捉异常,该异常也能进一步向上抛出直至被处理或引发进程崩溃?可是说到底,这和程序自然崩溃有什么区别呢?
---- 以上为自言自语,下面是问题 ----
抛出异常和返回false的区别是什么,两者在什么场景下使用?
回复内容:
首先,这是一个好问题。深入理解二者的区别是突破中等程度程序员的标志之一。先澄清一个误区,那就是异常非常慢。异常的实现需要保存异常抛出点到异常捕获点的必要信息,这是人们诟病异常性能的主要依据。但是这是错误的。第一,手工按照返回错误的风格取得行为等价于异常的实现性能绝大多数时候比不上语言内置的异常的性能。对于支持原生异常的OS,如Windows,这个差距尤其明显;第二,对于非基于栈的调用实现,异常和返回错误性能几无差别,只是风格不同而已。
回到问题,异常和返回错误的本质区别是什么?答:异常是强类型的,类型安全的分支处理技术;而返回错误是其弱化的,不安全的版本。
先看返回错误的特征。一般来说,需要用特别返回值来标识错误,意味着需要重载特定值得含义。假设一个操作会返回一个int型值,因为其不可能返回负数(如求绝对值),我们一般可以使用-1来作为操作失败(如函数库调用加载错误)的指示。-1在int类型中并无特别含义,然而我们这里强制施加了语义,而这种语义是弱的。没办法通过类型系统检查来确保正确性。
一个增强的办法是同时返回两种值。有的语言内置支持,没有内置支持的可以通过定义一个含有分别表征正确返回类型和错误类型的结构来模拟。这样的好处是传递信息的通道被分离了。
无论如何返回错误,它存在着一个显著的缺点:调用方必须显式检查错误值。当错误发生,必须终止当前操作,返回错误的时候,一般需要定义全新的错误类型。这导致操作不可任意简单组合,如模块B调用模块A发生错误的时候需要返回B定义的错误,而模块C调用A错误时则需要返回C定义的错误,而这两类错误往往是不兼容的。组合相关代码必须加入大量的粘连代码,这导致了代码膨胀,而且非常容易出错。对于接口定义明确的系统,一般定义一套通用的错误码来简化其复杂性。OS内核就是一个例子,它提供了一个适配所有OS调用的错误码表。然而其内部使用的错误码要多得多,并且往往在接口把内部错误码映射到外部错误码。
异常是一种安全的分支处理技术。因为它和错误处理密切相关,人们容易直接把异常看成是错误处理,连名字“异常”都带着浓浓的错误的含义。但是这是一个误解。异常的理论基础是假设某些分支处理中,一个分支和其它分支比起来发生的非常不频繁。与其平等地针对常见和极其罕见的情形进行处理(想一下,正常处理代码和错误处理代码往往一样多,大部分情况下后者其实更多),不如仅仅处理正常的情形,把不常见的情形归于一处统一处理。这样我们书写代码的时候仅仅关注正常情形就可以了。发生错误的时候,特别的流程会帮助程序员直接回到定义了错误处理的地方。
这样说有点过分简化。一般情况下,不能直接跳回。因为在异常抛出点到异常处理点之间,可能存在处于非一致状态的值,等待释放的资源等。所以一般情况下,特殊流程要回溯调用栈,确保执行的事务性。但是仅仅这个特殊流程是不够的,必须有合适的配套代码才行。这导致了额外的复杂性。C++引入的RAII概念是一个创举,然而依然没能全部消除程序员的工作。
因为异常是一个具体的类型,一个函数的signature就不仅仅是输入参数列表,输出参数加函数名,还要包含可能抛出异常列表。因为各个模块定义的异常层次结构迥异,这导致了额外的组合困难。然而和返回错误值的组合困难不同,前者导致的是编译时类型错误,后者则是运行时错误。一般来看,错误暴露的越早越好,我们倾向于前者。
理想情况下,一个异常结构完备的系统不会有运行时错误(大概如此,不展开)。然而因为上面提到的原因,在现有的异常支持的情况下,代码同样复杂,冗余,难以维护。
上面就是异常和错误的基本区别。
第二部分预告:有解决上述问题的优雅方法吗?
我的观点是有。但是因为现有能力还不到不借助任何参考直接澄清此问题,我回留待仔细斟酌,沐浴焚香,换到非手机输入的情况下给出,尽请期待。 都是错误处理的策略,OO语言更倾向异常,相比较判断一个函数可能的错误状况来说,“抛出”状态完整的异常对象被认为是更好的封装 ;你说的情况下,错误即false是最简单的情况,这种情况下,异常未必有优势;一般认为用异常可以简化复杂的错误处理代码,并且只要程序不需要终止执行,try catch比if else的代码更可读(错误处理的策略明显,状态可以更丰富,虽然这不是绝对的)。
result = func(); if (result === ERR_NO_1) { ... } else if (result === ERR_NO_2) { } else { ... }
<span class="k">if</span><span class="p">(</span><span class="n">jsonObj</span><span class="p">.</span><span class="n">has</span><span class="p">(</span><span class="s">"xxx"</span><span class="p">))</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="n">jsonObj</span><span class="p">.</span><span class="n">has</span><span class="p">(</span><span class="s">"xxxxx"</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//......... </span> <span class="k">return</span> <span class="nb">true</span><span class="p">;</span> <span class="p">}</span> <span class="p">}</span> <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
异常有两类,一类是『我知道这个地方可能出错,调用方必须明确知道出错的风险』,另一类是『这就是个错误,没啥挽救余地了崩溃拉倒』。这两类异常放Java里就是checked exception和unchecked exception的区别。
异常并不仅限于错误处理,很多时候是用来分开处理normal scenario和edge case的。比如说读取一个文件,把文件中每个词出现次数统计一下。这里用Python语法:
<span class="n">word_count</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span> <span class="k">try</span><span class="p">:</span> <span class="n">word_count</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span> <span class="n">word_count</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
设计成返回bool或指针的函数,就不需要异常。
也就是说异常和返回值是永远不同时存在的(当然这是我个人的理解)。
(我觉得,你问题中的add函数如果有可能失败,那么就不抛异常,如果正常情况下不应该失败,那么可以抛异常。但并不一定需要在每一个add函数的地方都加try。加不加得看你的程序逻辑能否以及应该恢复..(这时你也可以写一个辅助函数在其内部调用try add..其他地方使用这个辅助函数:),继续跑。否则就在程序入口加个try,然后退出即可)
好像还没答全你的这个好问题,明天电脑上再讨论讨论。 能返回Either或者Maybe就方便了, 像Either这样错误信息够丰富的情况下根本不需要异常 从WINDOWS实现上来讲一个分支语句,一个是SEH或者全局回调处理,后者可以很好的防止不再预料的情况时程序奔溃! 第一,异常都是可以预见的,所以它有可预知性。第二,异常不关心发生的条件而关心如何善后。第三,异常是被定义过的错误,比较容易定位问题。第四,异常可以传递。
执行失败的结果就是直接退出。。。。 假设你对某个异常(或者说执行错误)需要这样处理:
——在用户界面显示一条错误信息。
但是这个异常是由底层的API,比如数据库调用抛出的,而客户端没有直接调用这个API的权限。
这时候,你可以选择:
- 抛出异常,一层一层抛出
- 定义错误代码,一层一层返回
- 发现每一个函数都增加了一个叫err的传入参数,这个参数并没有什么卵用,因为它会被不加处理地返回给上一层,直达UI。
- 这并没有什么问题,但是有一天你被告知某个底层改动导致这个API会抛出一种新的错误,老板要求你对这种错误在调用栈里的某一层处理掉。于是你增加了对异常类型的判断。
- 后来,另一个新的模块需要复用你在上次处理的那个module里写的异常信息,你为了不c&p代码,把异常信息封装成了一个Error类,每个从Error继承来的子类都保存着自己独有的异常信息。
- 你对自己造的轮子很满意,然后用到了现在维护的模块中——现在你的代码看起来是这样:跨函数error code。 强制错误检查。 happen path 简化。 最后一个,你得会写异常安全的代码。
def f(err, **kwargs): result = None if(err.code == 1): handle_this_err(err) elif(err.code == 2): return (err, result) else: result = handle_data(**kwargs) return (None, result)
Salin selepas log masuk

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Konsep dan kejadian kelas dan kaedah Kelas (Kelas): digunakan untuk menerangkan koleksi objek dengan sifat dan kaedah yang sama. Ia mentakrifkan sifat dan kaedah yang biasa kepada setiap objek dalam koleksi. Objek ialah contoh kelas. Kaedah: Fungsi yang ditakrifkan dalam kelas. Kaedah pembinaan kelas __init__(): Kelas mempunyai kaedah khas (kaedah pembinaan) bernama init(), yang dipanggil secara automatik apabila kelas dijadikan instantiated. Pembolehubah instance: Dalam pengisytiharan kelas, atribut diwakili oleh pembolehubah tersebut dipanggil pembolehubah instance. Instantiation: Buat contoh kelas, objek khusus kelas. Warisan: iaitu, kelas terbitan (derivedclass) mewarisi kelas asas (baseclass)

jQuery ialah perpustakaan JavaScript klasik yang digunakan secara meluas dalam pembangunan web Ia memudahkan operasi seperti pengendalian acara, memanipulasi elemen DOM, dan melaksanakan animasi pada halaman web. Apabila menggunakan jQuery, anda sering menghadapi situasi di mana anda perlu menggantikan nama kelas elemen Artikel ini akan memperkenalkan beberapa kaedah praktikal dan contoh kod tertentu. 1. Gunakan kaedah removeClass() dan addClass() jQuery menyediakan kaedah removeClass() untuk pemadaman

class是python中的一个关键字,用来定义一个类,定义类的方法:class后面加一个空格然后加类名;类名规则:首字母大写,如果多个单词用驼峰命名法,如【class Dog()】。

Apabila bermain permainan seperti Grand Theft Auto V, ramai pemain suka menggunakan Mod untuk meningkatkan keseronokan dan kebolehmainan permainan. Sebagai alat pengurusan Mod yang terkenal, OpenIV boleh memudahkan proses pemasangan dan pengurusan Mod. Jadi, mari kita lihat cara menambah Mod pada OpenIV. Mula-mula, anda perlu memastikan anda telah memuat turun dan memasang OpenIV. Ia boleh didapati di laman web rasmi OpenIV (https://openiv.com/)

Apabila menulis kod PHP, menggunakan kelas adalah amalan yang sangat biasa. Dengan menggunakan kelas, kami boleh merangkum fungsi dan data yang berkaitan dalam satu unit, menjadikan kod lebih jelas, lebih mudah dibaca dan lebih mudah diselenggara. Artikel ini akan memperkenalkan penggunaan PHPClass secara terperinci dan menyediakan contoh kod khusus untuk membantu pembaca memahami dengan lebih baik cara menggunakan kelas dalam projek sebenar untuk mengoptimumkan kod. 1. Cipta dan gunakan kelas Dalam PHP, anda boleh menggunakan kelas kata kunci untuk mentakrifkan kelas dan mentakrifkan sifat dan kaedah dalam kelas.

Ralat Vue: Tidak dapat menggunakan v-bind untuk mengikat kelas dan gaya dengan betul, bagaimana untuk menyelesaikannya? Dalam pembangunan Vue, kami sering menggunakan arahan v-bind untuk mengikat kelas dan gaya secara dinamik, tetapi kadangkala kami mungkin menghadapi beberapa masalah, seperti tidak dapat menggunakan v-bind dengan betul untuk mengikat kelas dan gaya. Dalam artikel ini, saya akan menerangkan punca masalah ini dan memberi anda penyelesaian. Pertama, mari kita fahami arahan v-bind. v-bind digunakan untuk mengikat V

Bagaimana jquery menentukan sama ada elemen mempunyai kelas: 1. Tentukan sama ada elemen mempunyai kelas tertentu melalui kaedah "hasClass('classname')" 2. Tentukan sama ada elemen mempunyai kelas tertentu melalui "is('.classname ')" kaedah.

Latar Belakang Baru-baru ini, kod perniagaan utama telah disulitkan untuk rangka kerja syarikat untuk mengelakkan kod kejuruteraan daripada mudah dipulihkan melalui alat penyahkompilasi seperti jd-gui Konfigurasi dan penggunaan skim pengeliruan yang berkaitan adalah agak rumit dan terdapat banyak masalah untuk projek springboot, jadi fail kelas disulitkan dan kemudiannya Peloder kelas tersuai dinyahsulit dan dimuatkan Penyelesaian ini tidak benar-benar selamat Ia hanya meningkatkan kesukaran penyahkompilasian Ia menghalang lelaki tetapi bukan penjahat dalam rajah di bawah. Pemalam maven menyulitkan kompilasi menggunakan pemalam maven tersuai Fail kelas yang ditentukan disulitkan, dan fail kelas yang disulitkan disalin ke laluan yang ditentukan.
