71

What is the difference between Java exception handling and using assert conditions?

It's known that Assert is of two types. But when should we use assert keyword?

Hash
  • 4,647
  • 5
  • 21
  • 39
JavaResp
  • 2,253
  • 5
  • 24
  • 25
  • 1
    I cannot believe my eyes: this question was actually edited by a 166k user and it still looks like this! – Mike Nakis Sep 23 '14 at 15:46
  • 1
    Yeah, pretty bad. I cleaned it up some more. Not sure what JavaResp means by "two type" so left that in there. My best guess is pre-condition vs post-condition as per http://www.deitel.com/articles/java_tutorials/20060106/Assertions.html – Tim Abell Oct 09 '14 at 16:12
  • "Some more" meaning "entire revamp" in this case. – Jake Lee Oct 09 '14 at 16:14

10 Answers10

105

Use assertions for internal logic checks within your code, and normal exceptions for error conditions outside your immediate code's control.

Don't forget that assertions can be turned on and off - if you care about things like argument validation, that should be explicit using exceptions. (You could, however, choose to perform argument validation on private methods using assertions, on the grounds that a violation at that point is due to an internal bug rather than an external error.)

Alternatively it's entire reasonable (IMO) to use exceptions for everything. I personally don't use assertions much at all, but it's a matter of personal preference to some extent. (There can certainly be objective arguments for and against assertions, but it's not sufficiently clear cut to remove preference altogether.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 10
    It's worth noting that some languages actually implement assertions using exceptions. In such languages your statement that "it's reasonable to use exceptions for everything" is so true it's redundant. :) – Imagist Aug 14 '09 at 07:26
  • 1
    As specified by [dasblinkenlight](http://programmers.stackexchange.com/a/137167/175034) : "Unchecked exceptions are designed to detect programming errors of the users of your library, while assertions are designed to detect errors in your own logic. These are separate issues that should not be mixed." – MaxZoom Nov 13 '15 at 23:03
  • assetion in run time? – Manjitha Teshara Aug 06 '18 at 06:27
  • and exception in executing timetime? – Manjitha Teshara Aug 06 '18 at 06:28
  • @teranteshara: I'm afraid I don't understand what you're asking. – Jon Skeet Aug 06 '18 at 07:00
  • @teranteshara: I'm sorry, I still don't understand your question. Do you mean "Are assertions checked at execution time?" Do you mean "How can I create an assertion error myself at execution time?" Do you mean something else? It may be worth asking a new question rather than using comments here. – Jon Skeet Aug 06 '18 at 07:21
  • yes,this is what i'm asking .Are assertions checked at execution time? – Manjitha Teshara Aug 06 '18 at 08:19
  • 1
    @teranteshara: Yes, they're *only* checked at execution time (unless you have a special extra compile-time plugin). But they're only checked if they're enabled. See https://docs.oracle.com/cd/E19683-01/806-7930/6jgp65ikq/index.html – Jon Skeet Aug 06 '18 at 08:29
  • **Question**: What do you mean by "*normal exceptions*"? – Sebastian Nielsen Dec 29 '19 at 12:19
  • @SebastianNielsen: As opposed to assertions. – Jon Skeet Dec 29 '19 at 15:47
  • @Imagist No, it’s not really redundant in that case. The salient feature of assertions is that they can be turned on or off: if you want to _always_ check something no matter the build/run profile then you should use something that can’t be disabled instead of assertions. Doesn’t matter how the assertions are implemented. – Guildenstern Jan 07 '23 at 00:06
30

Java assertions are built on top of Java exceptions and exception handling. Indeed, when a Java assertion fails, the result is an AssertionError exception that can be caught like any other Java exception. The key differences between exceptions and assertions are:

  • Assertions are intended to be used solely as a means of detecting programming errors, aka bugs. By contrast, an exception can indicate other kinds of error or "exceptional" condition; e.g. invalid user input, missing files, heap full and so on.
  • The Java language provides syntactic support for assertions, in the form of the assert statement. Compare the following:

    if (x != y) {
         throw new SomeException("x != y");
    }
    
    assert x != y;
    
  • Most importantly, Java allows you to enable or disable assertion checking globally or on individual classes when you start the JVM.

Note: some people say that you should always run production code with assertion checking turned off. I tend to disagree with this as a blanket statement. If your production code is known to be stable AND you need to squeeze that last bit of performance out of it, then turning off assertions is good. But, if a (say) 10% performance hit is not a real problem, I'd prefer to have an application die with an assertion error if the alternative is continue and corrupt my database.

@Mario Ortegón commented thus:

The "turning off" is because assertions can be used to verify the result of an optimized algorithm by comparing its implementation against a well-known, but slow, algorithm. So, in development it is OK to invoke that O(N^3) method to assert that the O(log N) algorithm works as intended. But this is something that you do not want in production.

Whether or not you think it is good practice to turn off assertions in production, it is definitely bad practice to write assertions that have a significant impact on performance when enabled. Why? Because it means that you no longer have the option of enabling assertions in production (to trace a problem) or in your stress / capacity testing. In my opinion, if you need to do O(N^3) pre/post-condition testing, you should do it in your unit tests.

grg
  • 5,023
  • 3
  • 34
  • 50
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • The "turning off" is because assertions can be used to verify the result of an optimized algorithm by comparing its implementation against a well-known, but slow, algorithm. So, in development it is ok to invoke that O(n3) method to assert that the O(log N) algorithm works as intented... But is something that you *do not* want in production. – Mario Ortegón Aug 14 '09 at 07:39
  • Yes, I think the point about expensive checks is often glossed over. Cheap checks can be done by check-or-throw. Java assertions however really shine when you have a really nice check method which is expensive but could really help you out while developing—or later in production (by restarting with `-ea`) if you need to hunt down a bug. – Guildenstern Jan 07 '23 at 00:10
6

Exception is a mechanism of checking if the implementation is executing without any expected or unexpected errors or not. So, we see that exceptions are basically used for handling even the unforseen conditions during the execution of an application in a better way and hence using exceptions effectively results into a robust application.

Assertions should never be a part of the implementation of some functionality of the application. They should only be used to verify the assumptions - just to be sure that whatever we assumed while desinging the solution is actually valid in practical as well.

reference: http://geekexplains.blogspot.com/2008/06/asserions-in-java-assertions-vs.html

firstthumb
  • 4,627
  • 6
  • 35
  • 45
5

Assertions are very similar to exceptions, in fact just like exceptions they will flag a problem, but unlike exceptions - they won’t suggest any alternative execution path, but will simply fail. Why use assertions, if you can do the same thing, plus more with exceptions ?

Use them when the problems should not be fixed, and actually SHOULD NEVER HAPPEN IN THE FIRST PLACE. This sounds weird at first: don’t we want to safeguard our code from ALL potential problems ? Usually yes. But there is a case where we don’t. This case is called: “Design by contract”.

Let say you are writing an application for a bank. As a developer you can not possibly support all possible financial conditions. So before starting to code, you get a spec from the bank which gives you the valid ranges that this application should support. So your application is designed by a contract (by the spec from the bank). This contract will define the fundamental principles that should always be true in order for your application to work. These fundamental principles are called “invariants” (because they can’t change). Design by contract simplifies your life as a developer - you are only responsible to support the scope of work defined in the contract.
Its important to check the values of these invariants in your code, but you shouldn’t check them as if they are exceptions and try to work around them. If they are wrong - you must fail because the inputs have not fulfilled their contractual obligations.

The interesting thing is: if you don’t put an assertion into the critical place and invariants become invalid - your code will fail anyway. You just won’t know why. So to summarize - assertions are used for verifying the invariants. They go hand-in-hand with the “design by contract” principle. Use them to debug a problem, thats why they are turned off in production.

Another use case: if you are relying on an external library that you don’t completely trust - you may want to use assert statements when calling it.

Some also use assertions as a quick and dirty substitute for an exception (since its so easy to do), but conceptually that is not the proper thing to do.

3

Although, I have posted the answer in se.stackexchange site, that might be still helpful to post here.

Assertions are used,

  1. When you want to stop the program immediately rather to proceed with an unwanted state. This is often related to the philosophy of the Fail-fast [ 1 ] system design.

  2. When there are certain possibilities of cascading failures (i.e. in microservices) for the first unexpected condition that might lead the application into severe inconsistent or unrecoverable states.

  3. When you want to detect bugs in your system exclusively in the debugging period. You might want to disable them in production if language supports.

  4. When you already know that the unexpected conditions arose due to your internal miss-implementation and external system (i.e the callers) has no control over the unwanted state.

Exceptions are used,

  1. When you know that the unexpected conditions arose due to external systems fault (i.e. wrong parameters, lack of resources etc).

  2. When you know that the conditions can be backed up with alternative paths keeping the application functional qualities still intact (i.e. might work well for another call with proper parameters from the caller or external system).

  3. When you want to log and let the developers know about some unwanted state but not a big deal.

Note: “The more you use assertions, the more robust system you get”. In contrast “The more you use exceptions and handle them, the more resilient system you get“.


[ 1 ] Fail fast - In systems design, a fail-fast system is one which immediately reports at its interface any condition that is likely to indicate a failure. Fail-fast systems are usually designed to stop normal operation rather than attempt to continue a possibly flawed process. Such designs often check the system's state at several points in an operation, so any failures can be detected early. The responsibility of a fail-fast module is detecting errors, then letting the next-highest level of the system handle them.

Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
3

Example of a good use of Assert:

assert flibbles.count() < 1000000; // too many flibbles indicate something is awry
log.warning("flibble count reached " + flibbles.count()); // log in production as early warning

I personally think that Assert should only be used when you know something is outside desirable limits, but you can be sure it's reasonably safe to continue. In all other circumstances (feel free point out circumstances I haven't thought of) use exceptions to fail hard and fast.

The key tradeoff for me is whether you want to bring down a live/production system with an Exception to avoid corruption and make troubleshooting easier, or whether you have encountered a situation that should never be allowed to continue unnoticed in test/debug versions but could be allowed to continue in production (logging a warning of course).

cf. http://c2.com/cgi/wiki?FailFast see also my c# copy of this answer: Debug.Assert vs. Specific Thrown Exceptions

Community
  • 1
  • 1
Tim Abell
  • 11,186
  • 8
  • 79
  • 110
  • 3
    Assertions are much, *much* stronger statements than that. They're meant to document (and when running in debug, to verify) your assumptions and/or guarantees about what will *always* be true at a particular point in the code. **Assertion failures should never, ever happen** -- if they do, it means that (a) your assumptions were wrong, and (b) any code from then on can't be trusted to do the right thing (cause somewhere along the line, it's *already done* the wrong thing, and now it's operating "out of bounds"). – cHao May 11 '11 at 14:50
  • If you know that something should never happen then why would you let it pass unchecked in production code where assertions are turned off? Surely you would use an exception to make sure the broken assumption is caught. I know I'm going against the received wisdom here, but I'm interested to see what compelling arguments I can unearth by being contrarian. Thanks for your comment! – Tim Abell May 12 '11 at 12:03
  • 1
    Exceptions are for stuff that doesn't normally happen, but might. Missing files, network outages, perhaps invalid data. Stuff your code can't control. Assertions are for stuff that, if your code is working properly, *never* happens. They're meant as a double-check while debugging. In production, your code should already be sure enough of the result that it doesn't even have to check anymore. – cHao May 12 '11 at 13:13
  • Doesn't that rather presume that the code (and code around it) never changes? Code evolves in most environments I've seen, touched by many developers, nothing is certain. – Tim Abell May 12 '11 at 13:44
  • It presumes that developers won't be putting stuff into production without running it in debug mode first (and causing the code to fail whatever assertions it's invalidated). If the change causes an assertion failure, either your code is wrong (by making unwarranted assumptions) or theirs is (by breaking explicitly stated invariants), and that wrongness is severe enough that it should be fixed before ever considering putting the code in production. – cHao May 12 '11 at 14:05
  • I very much like the 'out of bounds' analogy. There is no point to continue once out of bounds, program must stop immediately. – Christophe Roussy Jan 28 '16 at 10:39
  • From a practical perspective, the assert concept may be stronger than @TimAbell says, but writing `throw AssertionError("Database corrupt")` is a much more fool-proof way to ensure the program does not continue in an unsafe state. – Josiah Yoder Feb 24 '16 at 19:27
  • For anything that could involve data loss I would say ensure there is an exception of some kind. For other cases though it is enough to assert in development and do nothing in production. Often you call down through 10 layers of methods. If each method checks the same parameter you are doing the same validation 10 times. Assertions let you remove that burden so those checks don't get done at run time. But of course you still have to handle bad data coming from the user and bring it into proper range or reject. That should all happen at your most 'public' part of the program. – LegendLength Jul 08 '17 at 08:17
1

Assert is for debugging purpose only and its trigger condition should not happen (null pointer when there shouldn't be, etc.)

Exception is for special system events that may always happen : FileNotFound, ConnectionToServerLost, etc.

Lliane
  • 831
  • 2
  • 7
  • 15
1

Assertion and Exception Handling both can assure programme correctness and avoid logic error,

but assertion can enable and disable as programmer wish,

in compiler if you use "java -ea JavaFileName" or "java -enableasserations JavaFileName" you can compile with assertion

if programmers don't need it ,"java -da JavaFileName " or "java -disableasserations JavaFileName " they can disable assertion.

this facility not in Exception handling

Manjitha Teshara
  • 562
  • 2
  • 8
  • 21
0

Assertion is used for debugging of the required assumptions to be checked at runtime only by enabling the assert feature while exception is to check the specific conditions to be checked during execution of the program to prevent the program from terminating.

SBTec
  • 709
  • 5
  • 8
0

Use exceptions for conditions you expect to occur, and user assertions for conditions that should never occur.

Usually, in a real-world project, you want exceptions to cover the conditions that should never happen and prevent the assertion from becoming true. After all, you want the program to operate and never get into that invalid state, so you should use exceptions and other techniques to ensure that the program never gets into such state. Sometimes, however, there are multiple ways that an assertion becomes true and you can anticipate at the time only few of them. So having these "hard-constraints" through assertions ensures that if in the future the program is in an invalid state that you haven't anticipated and that it shouldn't happen it will stop and you will have to investigate how this happened.

In other words, exceptions checks for invalid input data while assertions act as a mechanism for detecting bugs in your code.

Rafael
  • 7,002
  • 5
  • 43
  • 52