Search code examples
javaassertioneffective-java

What is the benefits to use assertion in Java's private methods


I'm reading Effective Java Item 49. I am a bit confused about the example using assertion to validate params in private methods.

Some posts explained why we can use assertions in private because public methods are responsible for ensuring that the correct arguments are passed. So no risk to use assertion for the private methods.

But why don't we use Objects.requireNonNull in private methods. And since assertion can be turned off, why do we still use it in private, it won;t do validation if we don't enable it?


Solution

  • We need to unpick what you mean by "validation".

    Case #1: If you are talking about internal consistency checks within your module, library or application, that you want to happen at test time, then assert statements are an appropriate way to do that.

    The kind of internal consistency checks that you might implement with assert statements could be expensive. For instance you might "assert" that some invariant is true after each operation. This extra checking could well alter the computational complexity of operations when asserting checking is on. You don't want this kind of validation to happen in production.

    Case #2: If you are talking about validation of external inputs to your application, using assert is not the right way to do it. The main reason is that Java assertion checking can be turned off. Indeed, they routinely are turned off in production; see above for the reason. But you don't want validation of external (e.g. user) input to be turned off because that is liable to cause other problems such as bad data in your database, vulnerabilities, etc.

    This kind of validation should not be done using assert.

    Case #3: Between those two cases above, we have the case where you are performing defensive validation on (say) parameters passed to some internal API within your code base.

    • Typically you don't want these checks to be turned off at runtime. Turning them off is liable to allow the effects of a problem (e.g. a previously undetected bug) to spread further.
    • But typically you don't also want the other internal assert checks (i.e. the "test time" checks from case 1) to be turned on because they are liable to be expensive.

    So that means that you probably should not be using assert for these tests either.


    According to the above reasoning, it doesn't really make any difference if the methods in which you are doing the validation are public, private or something else. Using assert or not is an orthogonal issue.

    Finally, it is worth saying that many Java programmers avoid using the assert statement entirely. A lot of the validation you would do using assert at test time can also be done using mocking. By not using assert at all, you avoid the scenario where someone creates performance problems for your application by turning on assertion checks in production!