如何以编程方式为特定类启用断言,而不是指定命令行参数“-ea”?
public class TestAssert {
private static final int foo[] = new int[]{4,5,67};
public static void main(String []args) {
assert foo.length == 10;
}
}
答案 0 :(得分:13)
尝试
ClassLoader loader = getClass().getClassLoader();
setDefaultAssertionStatus(true);
或
ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);
编辑:
基于评论
ClassLoader loader = ClassLoader.getSystemClassLoader();
loader.setDefaultAssertionStatus(true);
Class<?> c = loader.loadClass("MyClass");
MyClass myObj = (MyClass) c.newInstance();
public class MyClass {
private static final int foo[] = new int[]{4,5,67};
MyClass()
{
assert foo.length == 10;
}
}
答案 1 :(得分:9)
这是对@ bala的好答案的评论,但它太长了。
如果您只是启用断言然后调用您的主类 - 您的主类将在启用断言之前加载,因此您可能需要一个不直接引用代码中任何其他内容的加载器。它可以设置断言,然后通过反射加载其余的代码。
如果在加载类时未启用断言,则应立即将它们“编译出”,这样您就无法打开和关闭它们。如果你想要切换它们,那么你根本不需要断言。
由于运行时编译,如下所示:
public myAssertNotNull(Object o) {
if(checkArguments)
if(o == null)
throw new IllegalArgumentException("Assertion Failed");
}
应该像断言一样快速工作,因为如果代码执行很多并且checkArguments是假的并且没有改变那么整个方法调用可以在运行时编译出来,这将具有与断言相同的基本效果(This性能取决于VM。
答案 2 :(得分:1)
您也可以通过编程方式启用/禁用断言:
http://download.oracle.com/docs/cd/E19683-01/806-7930/assert-5/index.html
答案 3 :(得分:1)
最简单的&amp;最好的方法可以是:
public static void assertion(boolean condition, String conditionFailureMessage)
{
if(!condition)
throw new AssertionError(conditionFailureMessage);
}
无需将-ea设置为VM参数。
调用函数如:
assertion(sum>=n,"sum cannot be less than n");
如果断言失败,代码将给出AssertionError,否则代码将安全运行。
答案 4 :(得分:0)
可以使用 reflection 启用或禁用断言。与反射一样,该解决方案通常很脆弱,可能不适用于所有使用场景。但是,如果适用且可以接受的话,它比setClassAssertionStatus
更具灵活性,因为它允许在执行过程的各个点(即使在类初始化之后)启用/禁用断言检查。
此技术要求编译器生成综合静态字段,以指示是否启用了断言。例如,javac和Eclipse编译器都会为包含$assertionsDisabled
语句的任何类生成字段assert
。
可以验证如下:
public class A {
public static void main(String[] args) {
assert false;
System.out.println(Arrays.toString(A.class.getDeclaredFields()));
}
}
设置所需的断言状态仅取决于设置此字段(请注意反转的布尔值):
// Helper method in any class
public static void setAssertionsEnabled(Class<?> clazz, boolean value)
throws ReflectiveOperationException
{
Field field = clazz.getDeclaredField("$assertionsDisabled");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(Test.class, !value);
}