views:

982

answers:

8

Hi,

I'm wondering why the "assert" keyword is so underused in Java? I've almost never seen them used, but I think they're a great idea. I certainly much prefer the brevity of:

assert (param != null : "Param cannot be null");

to the verbosity of:

if (param == null) {
    throw new IllegalArgumentException("Param cannot be null");
}

My suspicion is that they're underused because

  • They arrived relatively late (Java 1.4), by which time many people had already established their Java programming style/habit
  • They are turned off at runtime by default, WHY OH WHY??

Cheers, Don

A: 

In fact they arrived in Java 1.4

I think the main problem is that when you code in an environment where you do not manage directly jvm options by yourself like in eclipse or J2EE servers (in both cases it is possible to change jvm options but you need to deeply search to find where it can be done), it is easier (I mean it requires less effort) to use if and exceptions (or worse not to use anything).

Denis R.
+13  A: 

assertions are, in theory, for testing invariants, assumptions that must be true in order for the code to complete properly.

The example shown is testing for valid input, which isn't a typical usage for an assertion because it is, generally, user supplied.

Assertions aren't generally used in production code because there is an overhead and it is assumed that situations where the invariants fail have been caught as coding errors during development and testing.

Your point about them coming "late" to java is also a reason why they aren't more widely seen.

Also, unit testing frameworks allow for some of the need for programmatic assertions to be external to the code being tested.

Ken Gentle
Excellent answer. I was going to mention junit and its brethren myself, and also that C also had an asset.h that was turned off by default for the same reasons as you give.
Paul Tomblin
@Ken Gentle: "method parameters are generally user supplied"?
Webinator
A: 

Assertions are very limited: You can only test boolean conditions and you need to write the code for a useful error message every time. Compare this to JUnit's assertEquals() which allows to generate a useful error message from the inputs and even show the two inputs side by side in the IDE in a JUnit runner.

Also, you can't search for assertions in any IDE I've seen so far but every IDE can search for method invocations.

Aaron Digulla
+5  A: 

From Programming with Assertions

By default, assertions are disabled at runtime. Two command-line switches allow you to selectively enable or disable assertions.

This means that if you don't have complete control over the run-time environment, you can't guarantee that the assertion code will even be called. Assertions are meant to be used in a test-environment, not for production code. You can't replace exception handling with assertions because if the user runs your application with assertions disabled (the default), all of your error handling code disappears.

Bill the Lizard
+18  A: 

It's an abuse of assertions to use them to test user input. Throwing an IllegalArgumentException on invalid input is more correct, as it allows the calling method to catch the exception, display the error, and do whatever it needs to (ask for input again, quit, whatever).

If that method is a private method inside one of your classes, the assertion is fine, because you are just trying to make sure you aren't accidentally passing it a null argument. You test with assertions on, and when you have tested all the paths through and not triggered the assertion, you can turn them off so that you aren't wasting resources on them. They are also useful just as comments. An assert at the start of a method is good documentation to maintainers that they should be following certain preconditions, and an assert at the end with a postcondition documents what the method should be doing. They can be just as useful as comments; moreso, because with assertions on, they actually TEST what they document.

Assertions are for testing/debugging, not error-checking, which is why they are off by default: to discourage people from using assertions to validate user input.

Adam Jaskiewicz
+4  A: 

In "Effective Java", Joshua Bloch suggested (in the "Check parameters for validity" topic) that (sort of like a simple rule to adopt), for public methods, we shall validate the arguments and throw necessary exception if found invalid, and for non-public methods (which are not exposed and you as the user of them should ensure their validity), we can use assertion instead.

yc

yclian
A: 

@Don, you are frustrated that assertion are turned off by default. I was also, and thus wrote this little javac plugin that inlines them (ie emits the bytecode for if (!expr) throw Ex rather than this silly assert bytecode.

If you include fa.jar in your classpath while compiling Java code, it will do its magic and then tell

Note: %n assertions inlined.

@see http://smallwiki.unibe.ch/adriankuhn/javacompiler/forceassertions

Adrian
A: 

I'm not sure why you would bother to write asserts and then replace them with a standard if then condition statement, why not just write the conditions as ifs in the first place?

Asserts are for testing only, and they have two side effects: Larger binaries and degraded performance when enabled (which is why you can turn them off!)

Asserts shouldn't be used to validate conditions because that means the behaviour of your app is different at run time when asserts are enabled/disabled - which is a nightmare!

Nimbus