Big*_*d_E 33 java assert nullable
我看过这个问题,但还有几个关于assert关键字用法的问题。我正在与其他一些编码人员讨论如何使用assert. 对于此用例,有一种方法可以在满足某些先决条件时返回 null。我编写的代码调用该方法,然后断言它不返回 null,并继续使用返回的对象。
例子:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Run Code Online (Sandbox Code Playgroud)
现在想象我像这样使用它:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Run Code Online (Sandbox Code Playgroud)
有人告诉我应该删除assert,它们不应该用于生产代码,只能用于测试。真的吗?
aku*_*ykh 24
Objects.requireNonNull(Object)为此使用。
检查指定的对象引用是否为空。此方法主要用于在方法和构造函数中进行参数验证,[...]
在你的情况下,这将是:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
Objects.requireNonNull(object); // throws NPE if object is null
// do stuff with object
}
Run Code Online (Sandbox Code Playgroud)
这个功能是为你想做的事情而设计的:明确标记什么不是null。好处是您可以null在不应该出现的地方找到-values。您将减少调试由nulls引起的问题的麻烦,这些 s 被传递到它们不应该存在的地方。
与assert. Whileassert是用于检查布尔值的关键字,Objects.requireNonNull(Object)是一个函数,可以更容易地嵌入代码中。
Foo foo = Objects.requireNonNull(service.fetchFoo());
// you cannot write it in one line.
Bar bar = service.fetchBar();
assert bar != null;
Run Code Online (Sandbox Code Playgroud)
service.foo(Objects.requireNonNull(service.getBar()));
// you cannot write it in one line.
Bar bar = service.getBar();
assert bar != null;
service.foo(bar);
Run Code Online (Sandbox Code Playgroud)
请记住,这Objects.requireNonNull(Object)仅用于null-checking 而assert用于一般断言。所以assert有不同的目的:主要是测试。它必须启用,因此您可以启用它进行测试并在生产中禁用它。使用它来将仅测试的测试与测试分开,或者更确切地说是检查,这也适用于生产代码。
jep*_*bio 23
关于断言要记住的最重要的事情是它们可以被禁用,所以永远不要假设它们会被执行。
为了向后兼容,JVM 默认禁用断言验证。它们必须使用 -enableassertions 命令行参数或其简写 -ea 显式启用:
java -ea com.whatever.assertion.Assertion
Run Code Online (Sandbox Code Playgroud)
因此,依赖它们并不是一个好习惯。
由于默认情况下不启用断言,因此您永远不能假设它们在代码中使用时会被执行。所以你应该总是检查空值和空的 Optionals,避免使用断言来检查公共方法的输入,而是使用未经检查的异常......一般来说,所有检查都好像断言不存在一样。
小智 11
当然,你被告知的是一个公然的谎言。这是为什么。
如果您只执行独立的 jvm,则默认情况下会禁用断言。当它们被禁用时,它们的占用空间为零,因此它们不会影响您的生产应用程序。但是,在开发和测试代码时,它们可能是您最好的朋友,并且大多数测试框架运行器都启用断言(JUnit 确实如此),因此您在运行单元测试时会执行断言代码,从而帮助您更早地检测任何潜在的错误(例如您可以为一些业务逻辑边界检查添加断言,这将有助于检测一些使用不适当值的代码)。
也就是说,正如另一个答案所暗示的那样,正是出于这个原因(它们并不总是启用),您不能依靠断言来进行一些重要检查,或者(尤其是!)维护任何状态。
有关如何使用断言的有趣示例,请查看此处- 在文件末尾有一个方法singleThreadedAccess(),该方法从第 201 行的断言语句中调用,用于捕获测试中任何潜在的多线程访问。
其他答案已经很好地涵盖了这一点,但还有其他选择。
例如,Spring有一个静态方法:
org.springframework.util.Assert.notNull(obj)
还有其他图书馆有自己的Assert.something()方法。自己编写也非常简单。
但是,请记住如果这是 Web 服务,您会抛出哪些异常。例如,前面提到的方法会抛出一个IllegalArgumentException异常,在 Spring 中默认返回一个 500。
对于 Web 服务,这通常不是内部服务器错误,也不应该是 500,而应该是 400,这是一个错误的请求。
| 归档时间: |
|
| 查看次数: |
7330 次 |
| 最近记录: |