What Does the Java Assert Keyword Do, and When Should It Be Used

What does the Java assert keyword do, and when should it be used?

Assertions (by way of the assert keyword) were added in Java 1.4. They are used to verify the correctness of an invariant in the code. They should never be triggered in production code, and are indicative of a bug or misuse of a code path. They can be activated at run-time by way of the -ea option on the java command, but are not turned on by default.

An example:

public Foo acquireFoo(int id) {
Foo result = null;
if (id > 50) {
result = fooService.read(id);
} else {
result = new Foo(id);
}
assert result != null;

return result;
}

What does the assert keyword do?

If you launch your program with -enableassertions (or -ea for short) then this statement

assert cond;

is equivalent to

if (!cond)
throw new AssertionError();

If you launch your program without this option, the assert statement will have no effect.

For example, assert d >= 0 && d <= s.length();, as posted in your question, is equivalent to

if (!(d >= 0 && d <= s.length()))
throw new AssertionError();

(If you launched with -enableassertions that is.)


Formally, the Java Language Specification: 14.10. The assert Statement says the following:

14.10. The assert Statement

An assertion is an assert statement containing a boolean expression. An assertion is either enabled or disabled. If the assertion is enabled, execution of the assertion causes evaluation of the boolean expression and an error is reported if the expression evaluates to false. If the assertion is disabled, execution of the assertion has no effect whatsoever.

Where "enabled or disabled" is controlled with the -ea switch and "An error is reported" means that an AssertionError is thrown.


And finally, a lesser known feature of assert:

You can append : "Error message" like this:

assert d != null : "d is null";

to specify what the error message of the thrown AssertionError should be.


This post has been rewritten as an article here.

Correct use Java assert keyword

Not in this case.

If you're asserting a value, you're making a statement that, before some critical evaluation is done using this value, that it is what you assert it to be. You can assert that the value isn't null, or that it's less than 2, or something before you reach your critical code block.

assert (mode >= 0 && mode < 2);  // Ensures that `mode` is between 0 and 1.
// Switch statement to follow

I would not encourage the use of that here. Your code would not read well, and unless you enable assertions with the -ea flag, your assertion would not work.

Instead, what you can do is throw an exception of some kind - if it's not 0 or 1, then the mode is an illegal value which cannot be processed, leading to exceptional/undefined behavior. Throw an exception of some kind.

switch(mode) {
case 0:
// do stuff
break;
case 1:
// do other stuff
break;
default:
throw new IllegalArgumentException("Mode is illegal");
}

what does the keyword assert means in java?

The assert keyword, as the name implies, makes an assertion about the code. It is used to specify something that holds true all the time -- or that, at least, should be true!

The assert keyword is followed by a boolean value (true or false), or an expression, to be evaluated at runtime, that returns a boolean.

assert true;
assert 1 == 1;

If, for any reason, the boolean expression evaluates to false, then an AssertionError is thrown.

// this will throw an AssertionError:
int x = 1;
assert x == 2;

When you use it, you make a clear statement about the state of your program on a given point, which can make it easier for readers to follow through your code.

There's a programming paradigm called program by contract, in which pieces of code make statements about the pre-conditions that must hold true for them to execute properly, and the post-conditions, that are guaranteed to hold true after their execution. You can use the assert keyword to implement this.

For example, if you write a method that calculates the square root of a number, it will only work for numbers that are greater than or equal to zero, and the result is guaranteed to satisfy the same conditions:

public double sqrt(final double x) {
assert x >= 0 : "Cannot calculate the square root of a negative number!"
double result = ...;
assert result >= 0 : "Something went wrong when calculating the square root!"
return result;
}

The most interesting aspect of assertions is that you can ask the compiler to remove them from the bytecode (by means of the -disableassertion argument), so that you won't get any kind of performance penalty at runtime on production. For this precise reason, it is of fundamental importance that the expression to be evaluate does not cause side-effects, that is, the expression should look like a pure mathematical function. Otherwise, the behavior of your program could change if the compiler removed your assertions.

Finally, if the assertions are compiled into the bytecode, they can be read by a software that will automatically generate tests that will try to break your code. It can be useful to find bugs earlier!

Assert keyword in Java

Assert will throw a runtime error (AssertionError) if its condition is false. Asserts give you a streamlined way of documenting, checking, and enforcing correctness criteria for your code. The benefits are a language-level hook for defining and manipulating these correctness conditions. To the extent that you wish to enable or disable them (there are arguments about whether or not this is a good idea) you can do so from the JVM command-line. Some commenters below note that assertions are disabled by default unless running in debug mode; my practice is to add "-ea" (enable assertions) in my wrapper scripts at all times. Even in performance sensitive code, for me the tradeoff weighs in favor of the security/correctness confidence I get from assertions. Assertions at Oracle and API Description for AssertionError

Note the distinction between expected or unexpected failures (exceptions), which may be outside your control, and assertion failures -- assertion failures document programmer assumptions, and indicate an incorrect program rather than an unexpected external condition or expected exceptional condition. If an assertion failure occurs, the interpretation is that the programmer has misunderstood or incorrectly expressed the program, rather than other sources of error or failure.

In practice, I use it to document obvious or non-obvious assumptions I make and invariants which I want to enforce as I produce (particularly private/internal) code, making it clear to myself and others why these assumptions are made, where they are made, and whether or not they are validated. Much better than comments to the same effect. This is a (small) step toward Design by Contract.

Effective Java item #38 "Check Parameters for Validity" (Google Books, Amazon.com) provides a useful presentation of the distinction between parameter checking and appropriate use of assertions.

Related on SO: (Enabling assertions in netbeans), (Assertions vs. Exceptions), (Near duplicate, asking for examples), (Badly named, but very similar content)

When to use an assertion and when to use an exception

Assertions should be used to check something that should never happen, while an exception should be used to check something that might happen.

For example, a function might divide by 0, so an exception should be used, but an assertion could be used to check that the harddrive suddenly disappears.

An assertion would stop the program from running, but an exception would let the program continue running.

Note that if(group != null) is not an assertion, that is just a conditional.

Is it good practice to use assert in Java?

The main reason assertions are not used is because they are not enabled by default. Therefore if you have a condition that is important enough to require an assertion you can't rely on assertions being enabled to get the job done.

As other answers have correctly stated they're designed for development-time testing and debugging because they cost nothing if assertions are disabled in production. I think it's better to create explicit tests in your testing framework (e.g. a unit test for edge conditions) than rely on someone enabling assertions while testing.

However a good example I've seen for using assertions is checking private method arguments. Since you control the access to those methods you can check that your own class is using the method correctly while your public methods use more reliable argument checking techniques (annotations, if statements, 3rd-party libraries, etc). That way even if assertions are disabled your method should be protected but developers looking at the source code can see the preconditions for your method and turn assertions on for an extra safety net when working on that class.

assert vs. JUnit Assertions

In JUnit4 the exception (actually Error) thrown by a JUnit assert is the same as the error thrown by the java assert keyword (AssertionError), so it is exactly the same as assertTrue and other than the stack trace you couldn't tell the difference.

That being said, asserts have to run with a special flag in the JVM, causing many tests to appear to pass just because someone forgot to configure the system with that flag when the JUnit tests were run - not good.

In general, because of this, I would argue that using the JUnit assertTrue is the better practice, because it guarantees the test is run, ensures consistency (you sometimes use assertThat or other asserts that are not a java keyword) and if the behavior of JUnit asserts should change in the future (such as hooking into some kind of filter or other future JUnit feature) your code will be able to leverage that.

The real purpose of the assert keyword in java is to be able to turn it off without runtime penalty. That doesn't apply to unit tests.

Should you assert not null with the assert statement in production code?

Use Objects.requireNonNull(Object) for that.

Checks that the specified object reference is not null. This method is designed primarily for doing parameter validation in methods and constructors, [...]

In your case that would be:

public void useObject(CustomObject customObject) {
object = customObject.getObject();
Objects.requireNonNull(object); // throws NPE if object is null
// do stuff with object
}

This function is made for what you want to do: explicitly mark what is not to be null. The benefit is that you find null-values right where they should not occur. You will have less troubles debugging problems caused by nulls that are passed somewhere where they shouldn't be.

Another benefit is the flexibility when using this function in contrast to assert. While assert is a keyword for checking a boolean value, Objects.requireNonNull(Object) is a function and can be embedded in code much easier.

Foo foo = Objects.requireNonNull(service.fetchFoo());

// you cannot write it in one line.
Bar bar = service.fetchBar();
assert bar != null;
service.foo(Objects.requireNonNull(service.getBar()));

// you cannot write it in one line.
Bar bar = service.getBar();
assert bar != null;
service.foo(bar);

Keep in mind that Objects.requireNonNull(Object) is only for null-checking while assert is for general assertions. So assert has different purposes: primarily testing. It has to be enabled, so you can enable it for testing and disable it in production. Use it to seperate testing-only-tests from tests, or rather checks, that are meant for production-code too.



Related Topics



Leave a reply



Submit