9

I'm reading the source of XWalkUIClientInternal and I ran into the following code:

    switch(type) {
        case JAVASCRIPT_ALERT:
            return onJsAlert(view, url, message, result);
        case JAVASCRIPT_CONFIRM:
            return onJsConfirm(view, url, message, result);
        case JAVASCRIPT_PROMPT:
            return onJsPrompt(view, url, message, defaultValue, result);
        case JAVASCRIPT_BEFOREUNLOAD:
            // Reuse onJsConfirm to show the dialog.
            return onJsConfirm(view, url, message, result);
        default:
            break;
    }
    assert(false);
    return false;

I've never really seen this technique nor really thought about it before, but I guess this essentially means "this is unreachable code and should not happen ever", and crash the app no matter what. Although technically you can do that with a Throwable, as long as it's not caught.

So my question is, which one is better and why, assert(false) or throwing a RuntimeException, or maybe an Error?

2 Answers 2

12

The biggest difference between

assert false;

(The parenthesis are not needed, assert is not a function but a statement.) and

throw new RuntimeException();

is that the assertion can be disabled. Actually, it is disabled by default unless the JVM is started with the -ea (“enable assertions”) flag. If assertions are enabled, assert false will unconditionally throw an AssertionError which derives from Error. But since assertions can be disabled, there are two problems,

  • the error might go undetected and
  • control flow analysis requires a dummy return statement after the assert (which is mostly clutter).

Therefore, in the above case, I'd certainly go with an explicit (and more concise)

throw new AssertionError("invalid type " + type);

instead of an assert followed by a dummy return.

As mentioned in the comments, this is assuming that type is an internal parameter and an invalid value indicates a bug in the logic itself. If it is an input parameter, it should be validated according to the usual rules and an IllegalArgumentException be thrown if validation fails.

Sign up to request clarification or add additional context in comments.

10 Comments

And if you wanted to throw something, would you throw a RuntimeException so that not even catch(Exception e) would catch it, or a subclass of Error?
You can throw an AssertionError, that's probably most appropriate. I have edited my answer accordingly.
Yes, you're right, that does seem like the best approach. It's more informative than just Assertion failed: false, and isn't caught by a mere catch(Exception e) branch.
Note that you can also add a custom error message to an assertion if you like. See this answer for a short example.
I disagree: I would rather use IllegalStateException is type is invalid rather than AssertionError. Any Error shouldn't be unless a serious condition occurred. Besides, the Javadoc states that AssertionError: Thrown to indicate that an assertion has failed.. It's specific to assert.
|
1

Following the Oracle guidelines (Programming with assertions), assertions was designed for testing purposes:

An assertion is a statement in the Java programming language that enables you to test your assumptions about your program. For example, if you write a method that calculates the speed of a particle, you might assert that the calculated speed is less than the speed of light.

Each assertion contains a boolean expression that you believe will be true when the assertion executes. If it is not true, the system will throw an error. By verifying that the boolean expression is indeed true, the assertion confirms your assumptions about the behavior of your program, increasing your confidence that the program is free of errors.

In your example, the developer assumed that the code never reaches the assert statement. If, by rare occurrence it does, the assert(false) will throw an Error (since it should never get there). This was done for testing purposes. So, use assert purely for testing purposes.

6 Comments

If it's for testing purposes, why does a unit test @Test public void test() { method(); } private void method() { assert false : "Crash me"; } pass?
@ᵺṓᵯᶏᵴ, are you referring to JUnit assertFalse() or java specific assert? JUnit's assertFalse validates that the condition is false so passing a false passes.I am not referring to JUnit or TestNG's assertFalse but rather Java's own assert.
I didn't use assertFalse() in my code. I used assert falseonly.
@ᵺṓᵯᶏᵴ your example throws an AssertionError with the message "Crash me".
Enable assert by running your application with a -ea argument.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.