1

I'm practicing a bit of Java SE 7 on my own and came across the following problem. I've written a public static void function ValidDate that takes in three strings and only throws an assertion error if the date is not valid. ValidDate uses two string arrays (MONTHS and DAYS) as libraries to validate the given date. ValidDate also has a unique assert expression at the end of each assertion test:

public static void ValidDate(String month, String day, String year){
    boolean validday = false;
    boolean validmonth = false;
    boolean validyear = true;

    try{
        Integer.parseInt(year);
    }catch(NumberFormatException e){
        validyear = false;
    }
    assert(validyear): "Error: year entry not written in integers.";


    for(String m:MONTHS){
        if(m.equals(month)){
            validmonth = true;
        }
    }
    assert (validmonth): "Error: month entry is not valid; must be an"
            + " integer between (0)1 and 12.";

    ...
}

My intent is to add ValidDate as a help function for a DOB setter (SetDOB) for my public class Person. The implementation would be to have ValidDate throw an exception when an invalid DOB is entered in the setter, and SetDOB would then output a message that the entered DOB was unacceptable and not change the current DOB value:

public void SetDOB(String newDOB){
    String[] dates = newDOB.split("/");
    boolean validdate = true;
    if(dates.length == 3){
        try{
            ValidDate(dates[0],dates[1],dates[2]);
        }
        catch(AssertionError e){
            System.out.println("Error: ValidDate threw an assert error.");
            validdate = false;
        }
        if(validdate){
            DOB = newDOB;
        }
    }
    else{
        System.out.println("Please enter a valid DOB of the form: Month/Day"
                + "/Year using integers.");
    }
}

When I attempted to run SetDOB with an invalid DOB, however, ValidDate would not throw an AssertionError for SetDOB to catch. No error messages were output either. I suspect that the cause of this is related to my use of try-catch statements in either ValidDate or SetDOB. However, I may have made a different mistake without realizing it as well. I want someone to explain what I did wrong and how to accomplish my intended task correctly. If someone else has already answered this or a similar question, then please add in a link to their post. I may also remove this post if I find it redundant when encountering the linked post.

Joe
  • 25
  • 7
  • It is better not to catch the `NumberFormatException` in the method, and pass that up to the caller: `NFE` is a lot more specific about the nature of the failure than `AssertionError`. – Andy Turner May 06 '16 at 21:52
  • Also: `validmonth = MONTHS.contains(month)`. No need for a loop. – Andy Turner May 06 '16 at 21:53
  • 1
    Make sure assertions are enabled in your environment. Either way, assertions are supposed to test code correctness; they're not meant for handling bad input. Use `IllegalArgumentException` instead. Also, by Java convention, the method should start with a lowercase letter. – shmosel May 06 '16 at 21:53

3 Answers3

2

However, the real problem is that you misunderstand the purpose of assertions. They are not there to indicate that something went wrong in the course of executing your program, but to indicate that your assumptions about your code are wrong.

When you write something like this

assert someValue != null : "some value should be set"

it means that you have written your code in such a way that someValue gets set one way or the other, and by the time the code reaches assert it must be set. If someone modifies your code so that it could reach the assert without setting someValue, the assertion would catch it.

Your code, on the other hand, tries to use assertions for validations. This is what exceptions are for:

if (!validmonth) {
    throw new InvalidMonthException("Error: month entry is not valid; must be an integer between (0)1 and 12.");
}

Note: the most likely reason why your code is not catching assertions is that you have not enabled them.

Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Assertions are for testing the invariants your code assumes. If an assertion ever fails, that should indicate that your code is wrong, never that some predictable failure mode has been encountered. Assertions are not suitable for the latter because whether assertions are evaluated at runtime at all depends on VM arguments.

It follows that it is rarely appropriate to catch AssertionError. (As, indeed, it is rarely appropriate to catch any Error.) Only under rather special conditions is there any plausible way to recover from the program itself being incorrect.

In your particular case, you are probably running your code without assertions enabled. You do not catch the AssertionError because none is ever thrown.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
0

Create your own exception class instead of throwing/catching AssertionError. Do not catch this exception in your SetDOB method, instead add a throws clause to setDOB method. Catch the exception when you invoke setDOB method.

PeaceIsPearl
  • 329
  • 2
  • 6
  • 19