断言与例外

时间:2013-08-07 19:26:04

标签: java exception exception-handling

我已经阅读了有关何时使用assert以及何时使用异常的一些信息。 我不清楚的是为什么?

例如: 断言旨在仅用作检测编程错误(即bug)的手段。相反,异常可以指示其他类型的错误或“异常”条件;例如用户输入无效,文件丢失,堆满等等。

现在: “断言只是用来检测编程错误的手段,也就是错误” - 现在看来,所有断言都被例外所取代?例外会做同样的事情吗?

“断言仅用于调试目的,不应发生其触发条件。” - :现在好吧如果我使用异常然后execptions然后永远不会抛出异常

根据我的理解,异常可以做所有断言,除非它们不能被禁用。 禁用是否应该使用它们的唯一理由?

是否有理由使用它们而不是何时使用它们?

由于

7 个答案:

答案 0 :(得分:3)

测试用例使用断言来确保您构建的内容在将来不会出现意外情况。例如,您可以断言以确保在错误输入时抛出异常。

在编程中多次更改一件事意味着您必须更改代码的其他部分。断言确保您更改的内容不会破坏您过去编写的代码。

例外是好的。它们是通过例外预期和处理的。例如,您有不正确的登录名和密码的例外。

您可以断言,如果登录名或密码不正确,则会引发预期的异常。

断言包含三个主要内容。您正在测试的内容(例如,函数名称,即sign_in),内容(函数参数,即{'email': 'john@example.com', 'password': hashlib.md5('my_password')}),以及出现的内容(assertTrue('user_name' in response, 'Expecting user_name to be in response!'))。

例外是代码中的正常,合理的替代方案。断言是测试,以确保逻辑路径应该遵循它们。

根据python unittest framework,您可以断言抛出异常:

import random import unittest

class TestSequenceFunctions(unittest.TestCase):

    def setUp(self):
        self.seq = range(10)

    def test_shuffle(self):
        # make sure the shuffled sequence does not lose any elements
        random.shuffle(self.seq)
        self.seq.sort()
        self.assertEqual(self.seq, range(10))

        # should raise an exception for an immutable sequence
        self.assertRaises(TypeError, random.shuffle, (1,2,3))


    def test_choice(self):
        element = random.choice(self.seq)
        self.assertTrue(element in self.seq)

    def test_sample(self):
        with self.assertRaises(ValueError):
            random.sample(self.seq, 20)
        for element in random.sample(self.seq, 5):
            self.assertTrue(element in self.seq)

if __name__ == '__main__':
    unittest.main()

答案 1 :(得分:2)

断言被设计为有选择地关闭,默认情况下它们是关闭的。你应该在有条件的情况下使用它们,但是如果你真的需要的话可以检查。认为它们比例外情况更为特殊。

异常及其检查始终开启。虽然例外但它们仍然可以随时出现。

断言可以检查编码错误,一旦你编程没有bug,就不需要它们。由于您可能无法控制的值(例如输入),因此可以触发例外。

答案 2 :(得分:1)

工作代码中的断言(而不是测试代码)用于检查提供给代码的值是否正确。如果值错误,则抛出断言异常。

您可以编写自己的代码来测试值,并抛出您自己选择的异常。

断言易于使用,并且与日志记录一样,可以在已经彻底调试的生产代码中关闭。此外,任何阅读代码的人都知道测试的原因而不考虑它。这样可以节省时间。 (当你回去读两年前写的代码时,它也会节省你的时间。)

无论哪种方式都有效。

答案 3 :(得分:1)

许多程序员将断言转换为发布代码中的异常检查。或者他们可能会使用两种不同的断言来转换一个而不是其他断言,如果某些断言对性能非常敏感。

这是防御性编程的一部分。断言应该记录不可能的条件。然而,现实生活中的程序员知道有时会发生不可能的情况,因为未经测试的代码路径,系统库中的错误或硬件错误。

将断言转换为异常通常几乎没有什么害处。可能发生的一些伤害是在Java中,它可能会将一种新的异常类型引入到以前没有的方法中。另一个危害可能是转换后的断言可能位于需要非常高性能的循环内,并且断言检查可能会使其减慢太多。

答案 4 :(得分:0)

我认为主要区别在于断言允许您看到问题早于异常发生。所以它为你提供了一个早期的执行点,试图对它做一些事情(或者根本没什么 - 让它失败)。因此,如果你想在真正糟糕的事情发生之前看看执行是如何进行的,你会使用它们(抛出异常)。

我能想到的一个戏剧性的类比是那些联盟号国防军输送火箭弹,偶尔你会听到自动火箭在开始时偏离航线并立即触发其“自毁”。我猜它就像一个断言,他们用它来确定火箭的航向是否正确(如果它是一个例外 - 到可能抛出的时候火箭可能已经击中了什么)。

答案 5 :(得分:0)

断言被设计为有选择地关闭,默认情况下它们是关闭的。你应该在有条件的情况下使用它们,但是如果你真的需要的话可以检查。认为它们比例外情况更为特殊。

异常及其检查始终开启。虽然例外但它们仍然可以随时出现。

断言检测编码错误。一旦你的程序没有bug,就不需要它们,可以关闭它们。例外检测不正确的使用或输入,无法安全关闭。

答案 6 :(得分:0)

我在生产代码中看到两个断言用例:

在方法的开头,您将正常检查给定参数是否有效。对于公共方法,您将使用if statments和exceptions。对于私有方法,您可以使用assert进行simelar检查。这个想法是为了避免在测试过程中对产品进行冗余检查(或者当出现问题时),你可以激活断言进行一些双重检查。

使用断言的另一个原因是记录以下代码中使用的假设。就像那样,一些值在这里被认为永远不会为空。

这里有一些示例代码

public class Exampel {
    public publicMethod(final Integer i) {
        if (i == null) {
            throw new RuntimeException("i should not be null");
        }

        privateMethod(i):
    }

    private privateMethod(final Integer i) {
        assert i != null;

        // do something
    }
}

你不想多次检查我的null。您只需假设正确使用privateMethod即可。你也给那些读取你代码的人提供了将null传递给privateMethod的提示是错误的。

相关问题