I really like the concept of assertions in Java in the way how to use them. It’s much easier than to write an if and then throw an Exception/Error.
But the thing I don’t understand is, why do they need to get enabled with -ea to work? That makes them unreliable and that’s the reason I don’t use them. What is the purpose of this decision and what is the purpose of assertions if they can be on or off and the program has to handle it?
2
I think it was a language design choice.
Some assertions can be time consuming, especially if they compare the output of some functions. Enabling assertions is like a “debug” flag. Whether that choice is a sensible one is a completely different matter.
The way I usually code is that for external/public methods, arguments are checked and IllegalArgumentsExceptions are thrown. And for internal/private methods, assertions about the arguments/results or in the code are used. It’s more concise and there is no performance impact when the code is released.
1
Assertions are not meant to replace checking method parameters or program state and throwing informative exceptions when facing an exceptional situation. Your program logic or your error handling logic shouldn’t rely on them.
The purpose an assertion is to force a program to fail when a simple self diagnosis shows there’s something wrong with the program itself. Assertions may help a programmer in finding bugs and avoiding them in the first place. Since all programming and debugging should be done in a development environment rather than in a production environment, assertions are usually disabled in production environments.
Generally, you should only use asserts to help yourself to find bugs in the method or the class the assert belongs to. You shouldn’t use asserts to inform some client module about an exceptional condition.
Java may have just copied this practice from C/C++, where assertions are disabled in an optimized build, as a common practice.
The reason for it to be this way in C/C++ is that assert creates additional branch in the code, which is not usually what you want in the release build.
The reason it might not matter that much in Java is that JIT will probably make the negative assert outcome branch asymmetric to compensate.
The reason it might still matter in Java is that certain optimizations may not be possible when a node in the program flow graph may throw. So code with assertions wiped out may be better despite the JIT aspect.
2