public static boolean areAssertsEnabled() {
boolean assertsEnabled = false;
assert assertsEnabled = true; // Intentional side effect!!!
return assertsEnabled;
}
参见 “要求启用断言”
boolean assertEnabled = false;
try {
assert false;
} catch (AssertionError e) {
assertEnabled = true;
}
ManagementFactory.getRuntimeMXBean().getInputArguments().contains("-ea");
兄弟姐妹的答案是正确的。但我质疑这种方法的实用性和普遍性。 (跳转至“替代方法”,了解解决此问题的另一种方法。)
启用断言的最简单方法是为所有类启用它们。
-ea
或:
-enableassertions
在这种情况下,您可以将该事实存储在一个变量中并在整个程序中使用它:
public class Main {
public static boolean assertsEnabled = false;
static {
assert assertsEnabled = true;
}
[…]
}
但是说我有课
Main, A, B, C
并且:
-ea:Main -ea:A
即仅对
Main
和 A
启用断言。因此,意图必须是不应该运行 B
和 C
内部的断言。
鉴于此:
public class Main {
public static boolean assertsEnabled = false;
static {
assert assertsEnabled = true;
}
public static void main(String[] args) {
System.out.println("Hello from main()");
m();
assert A.print();
A.print2();
assert B.print();
B.print2();
assert C.print();
C.print2();
}
private static void m() {
if (assertsEnabled) {
System.out.println(" main() again (using static variable)");
}
}
}
很清楚如何处理
print()
方法:它们将从 -ea:Main
开始运行。如果 -da:Main()
那么它们将不会运行。
m()
将打印字符串,因为我们知道 assertsEnabled
。
print2()
函数如下所示:
// C
public static void print2() {
if (Main.assertsEnabled) {
System.out.println(" assert inside C (using variable from Main)");
}
}
在这里,会发生什么也很清楚:程序将打印自
-ea:Main
以来的字符串以及我们初始化 Main.assertsEnabled
的方式。但请稍等:断言对于 C
是禁用的(实际上是 -da:C
)。那么这真的是我们想要的吗?也许。或者也许我们只是使用属于 Main
的静态变量,因为它足够方便,并没有考虑到这个 运行在 Main
:
public static boolean assertsEnabled = false;
static {
assert assertsEnabled = true;
}
与复制粘贴到
C
中的完全相同的代码的行为不同。
因此,根据 other 类的断言包含而采取不同行为的代码似乎可能会令人困惑。让我们将这段代码复制粘贴到每个使用断言的类中:
private static boolean assertsEnabled = false;
static {
assert assertsEnabled = true;
}
并像这样使用它:
if (assertsEnabled) {
// Error checking
}
但我认为有一种更直接的方法。
操作:
我想采用一些代码路径,仅当在启用断言的情况下调用 JVM 时才执行昂贵的检查。
x()
boolean
return true
来满足类型检查器的要求(也可以是您想要断言的任何内容,但由于您想检查断言是否已启用,然后运行一些代码,似乎检查比单个检查更复杂布尔表达式可以方便实现)
assert
放在所有
x()
的调用前面
assert x();
[…]
private static boolean x() {
// X
}
例如:
private static boolean x() {
var setup = new Setup();
assert ...;
assert ...;
[more setup and preparation]
assert ...;
return true;
}
交错常规代码和断言代码
关于断言的 Java 文章介绍了如何解决这个问题:
有时需要在执行计算之前保存一些数据以检查后置条件。您可以使用两个断言语句和一个简单的内部类来完成此操作,该内部类保存一个或多个变量的状态,以便在计算后检查(或重新检查)它们。 […]这是一个更简单且手动的示例:
private static void doWork(Work work) {
ConsistencyCheck cc = null;
assert ((cc = new ConsistencyCheck(work)) != null);
doWorkInner(work);
assert cc.check(work);
}
在禁用断言的情况下运行时,这里唯一的开销(如果 JIT 没有将其作为死代码删除)是将对象初始化为 null
,这应该不会很昂贵。