如何以编程方式启用断言?

时间:2011-04-05 21:25:36

标签: java configuration assertions

如何以编程方式为特定类启用断言,而不是指定命令行参数“-ea”?

public class TestAssert {

    private static final int foo[] = new int[]{4,5,67};


    public static void main(String []args) {
        assert foo.length == 10;
    }
}

5 个答案:

答案 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);
}