简体   繁体   English

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

[英]How to programmatically enable assert?

How can I programmatically enable assert for particular classes, instead of specifying command line param "-ea"?如何以编程方式为特定类启用断言,而不是指定命令行参数“-ea”?

public class TestAssert {

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


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

Try尝试

ClassLoader loader = getClass().getClassLoader();
setDefaultAssertionStatus(true);

or要么

ClassLoader.getSystemClassLoader().setDefaultAssertionStatus(true);

EDIT:编辑:

based on the comments根据评论

    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;
    }
}

This was a comment to @bala's good answer, but it got too long.这是对@bala 的好回答的评论,但它太长了。

If you just enable assertions then call your main class--your main class will be loaded before assertions are enabled so you will probably need a loader that doesn't reference anything else in your code directly.如果您只是启用断言然后调用您的主类——您的主类将在启用断言之前加载,因此您可能需要一个不直接引用代码中任何其他内容的加载器。 It can set the assertions on then load the rest of the code via reflection.它可以设置断言,然后通过反射加载其余代码。

If assertions aren't enabled when the class is loaded then they should be "Compiled Out" immediately so you are not going to be able to toggle them on and off.如果在加载类时未启用断言,那么它们应该立即“编译出”,因此您将无法打开和关闭它们。 If you want to toggle them then you don't want assertions at all.如果你想切换它们,那么你根本不需要断言。

Due to runtime compiling, something like this:由于运行时编译,是这样的:

public myAssertNotNull(Object o) {
    if(checkArguments) 
        if(o == null)
            throw new IllegalArgumentException("Assertion Failed");
}

Should work nearly as fast as assertions because if the code is executed a lot and checkArguments is false and doesn't change then the entire method call could be compiled out at runtime which will have the same basic effect as an assertion (This performance depends on the VM).应该几乎和断言一样快,因为如果代码被执行很多并且 checkArguments 是 false 并且没有改变那么整个方法调用可以在运行时编译出来,这将具有与断言相同的基本效果(此性能取决于虚拟机)。

You can enable/disable assertions programmatically too:您也可以通过编程方式启用/禁用断言:
http://download.oracle.com/docs/cd/E19683-01/806-7930/assert-5/index.html http://download.oracle.com/docs/cd/E19683-01/806-7930/assert-5/index.html

It is possible to enable or disable assertions using reflection .可以使用反射启用或禁用断言。 As usual with reflection, the solution is fragile and may not be appropriate for all usage scenarios.与反射一样,该解决方案很脆弱,可能并不适合所有使用场景。 However, if applicable and acceptable, it is more flexible than setClassAssertionStatus because it allows to enable/disable assertions checks at various points in the execution, even after the class is initialized .但是,如果适用且可接受,它比setClassAssertionStatus更灵活,因为它允许在执行的各个点启用/禁用断言检查,即使在类初始化之后也是如此

This technique requires a compiler that generates a synthetic static field to indicate whether assertions are enabled or not.这种技术需要一个编译器来生成一个合成静态字段来指示是否启用断言。 For example, both javac and the Eclipse compiler generate field $assertionsDisabled for any class that contains an assert statement.例如,javac 和 Eclipse 编译器都会为任何包含assert语句的类生成字段$assertionsDisabled

This can be verified as follows:这可以通过以下方式验证:

public class A {
    public static void main(String[] args) {
        assert false;
        System.out.println(Arrays.toString(A.class.getDeclaredFields()));
    }
}

Setting the desired assertion status just comes down to setting this field (note the inverted boolean value):设置所需的断言状态归结为设置此字段(注意反转的布尔值):

// 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);
}

The simplest & best way can be:最简单和最好的方法是:

public static void assertion(boolean condition, String conditionFailureMessage)
{
    if(!condition)
        throw new AssertionError(conditionFailureMessage);
}

No need to set -ea as VM argument.无需将 -ea 设置为 VM 参数。

call the function like:像这样调用函数:

assertion(sum>=n,"sum cannot be less than n");

If assertion fails, code will give AssertionError, else code will run safely.如果断言失败,代码将给出 AssertionError,否则代码将安全运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM