• Post Reply Bookmark Topic Watch Topic
  • New Topic

How to write try/catch for setters and getterts  RSS feed

 
Steven Greenbaum
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

In the set method The only things I could see that could go wrong would be null input or incorrect type

Do I catch just these exceptions or something more general.

I am not sure how or whether to write a try/catch for get. What is recommended?

Thank you


 
Stephan van Hulst
Saloon Keeper
Posts: 7963
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There would be no point, because those methods don't cause exceptions. What would be there to catch?

The setter will just set the field to null of you pass null. I don't know what you mean by "input of the wrong type".
 
Carey Brown
Saloon Keeper
Posts: 3310
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Setters often validate the input and throw an exception. You wouldn't want your object to be set to a corrupt state.
Haven't seen a need for it in getters but I suppose a contrived example might be if the getter were to do some sort of I/O (which is probably not a good idea to begin with).
 
Steven Greenbaum
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In response to Stephan
Wouldn’t an integer be of the wrong type?
 
Stephan van Hulst
Saloon Keeper
Posts: 7963
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Java is a statically and strongly typed language. You can never pass an integer to a method that accepts a string, the compiler won't accept code that attempts to do so.
 
Steven Greenbaum
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Aha - so it's nipped in the bud
 
Steven Greenbaum
Ranch Hand
Posts: 58
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not sure if I should start a new thread.

This is my most complicated class. I can't think of anything that obvious that would cause an error.
In my test program I set the input periods to -1. This caused a NegativeArraySizeException so I could catch that.

How would I catch a general error where i don't know the exception type in advance?

Also I would like to throw an exception if periods < 3 or greater than 120.

How would I do that?
Tx


 
Campbell Ritchie
Marshal
Posts: 56525
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Have you been through the Java™ Tutorials about exceptions? That will tell you how to handle exceptions, and also how to throw them. Many books only tell you how to handle exceptions.
Once you have read the tutorials section, you need to consider the concept of an invariant. This is something which must be maintained always. That's not quite true; a method may breach its object's invariants as long as it restores them before it completes. For a grade for a student (a common exercise), there are certain invariants, e.g. number of grades ≥ 0, ∀ grade • grade ≥ 0 ∧ grade ≤ 100. Now you might have an enterGrade method or setGrade.So you try passing -1, -1 to that method and you get an exception. Even better, you pass 1, 999999999 and have now recorded an incorrect grade.

You can consider changing the method to prevent that exception, possibly by having an if statement which does nothing for arguments outwith the permissible ranges, but that can cause confusion to the user.I'll let you work out whether the predicate in line 3 is correct and my error message in line 9 is helpful or not.

Your next line of defence is to supply documentation comments explaining how the method is supposed to work:-The character \u2019 is a posh apostrophe: ’   The characters ≥ and > are coded in the documentation comments by &geq; and &gt;
You still get the exception if you pass -1, -1, but now you can point to the documentation comments and tell off the user that it is their fault for not reading the instructions.
You can now move up one step in the arms race and move into the realms of assertive programming:-Those are unchecked exceptions, and that gives the user several options.
  • 1: If the input is hard-coded or read from a file, the code or file will need editing, so allow the program to crash.
  • 2: If the grade is entered by the user, that gives the program reading the input the option of verifying the correctness of the input earlier. If done correctly, that will obviate any need to deal with exceptions because they won't occur.
  • 3: The user has the option of catching an exception and going back to read new input.
  • Note that you are not forcing any options on the user of this code; users can decide for themselves what to do. But you need to warn the users about those exceptions. Note they are unchecked exceptions, so you shouldn't write a throws clause.Maybe I shou‍ld have said score or mark rather than grade.

    Note that I used the non‑specific RuntimeException; I could have declared IndexOutOfBoundsException and IllegalArgumentException separately. Don't declare ArrayIndexOutOfBoundsException, otherwise you may be committing yourself to implement the object with an array for ever. Note I could have used different kinds of exception in the documentation comment, but the important thing is that the user now knows what input the method takes, and what sort of exception to expect for wrong input. Now the user can decide whether to catch the exception or not, as I explained with the numbered points.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7963
    143
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    You shouldn't catch unchecked exceptions. When they arise, it means there is a bug in the code and you need to fix it. For instance, if your constructor gets passed a negative amount of periods, that means the client of the module doesn't adhere to the rules of your class, so simply let them crash and burn. In general, you only catch checked exceptions (like IOException) because it's not a programmer's fault when they happen.

    However, it's weird that your client would get a NegativeArraySizeException when they're not working with arrays. So you could check the parameters to throw an unchecked exception that's appropriate for the situation:

    However, if you want to support different ranges (such as 3 - 12), just edit the condition that causes the exception to be thrown. You can do the same with the date, employees and salary to check that they're not null when they get passed to your constructor. That way you can enforce that your fields will never hold null values, which is a great worry off your mind.

    A few remarks about your code:

    Don't use so many arrays. As you've noticed, arrays have a fixed length that needs to be known before you start processing elements. It's much better to use types from the Collections API. Lists and maps can grow dynamically.

    Give method parameters descriptive names. The client doesn't know what names such as p, d, e and s mean, so write those identifiers out.

    Don't ask for more than you need. The constructor of your class only needs a number of employees, so just pass an integer and not an Employees object.

    The client of your class needs to make sure that the employee indices they pass to your getters are consistent with the order they passed the employees into your process method. That's very brittle, and just begs for trouble in the future. Instead, give each employee a unique ID, and look them up by their ID. Maps are great for this purpose. Both the Employees class and the Salary class seem to do nothing more than maps, so just have your class accept maps instead.

    Your headCount field isn't actually a count of anything. It seems more like a strangely typed presence list. you should use a Map<X, Set<Y>> instead, where X is whatever type you use to identify a time period, and Y is whatever type you use to identify an employee. You can then get the presence of an employee during a certain period with precense.get(periodId).contains(employeeId).

    "Process" is one of the vaguest terms you can use for method names. Every method processes something. Instead, you could name the method something like generateYearlyFinancialReport().

    In general, you want to make classes immutable. Try not to change the value of fields after you've constructed an object. It appears you want to make a summary of some statistics, so create a class that holds those statistics and doesn't change them after an instance is created.

    Now for an example of using maps and enforcing invariants by throwing exceptions:

    Now, you try to implement the MonthlyFinances inner class.
     
    Dave Tolls
    Ranch Foreman
    Posts: 3056
    37
    • Likes 1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Stephan van Hulst wrote:You shouldn't catch unchecked exceptions. When they arise, it means there is a bug in the code and you need to fix it. For instance, if your constructor gets passed a negative amount of periods, that means the client of the module doesn't adhere to the rules of your class, so simply let them crash and burn. In general, you only catch checked exceptions (like IOException) because it's not a programmer's fault when they happen.


    That only works if you are both in an environment where checked exceptions are not considered a Bad Thing, and are not using a framework where that view is held.

    For example all exceptions from Hibernate are RuntimeExceptions, similarly with Spring.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Stephan van Hulst wrote:You shouldn't catch unchecked exceptions. When they arise, it means there is a bug in the code and you need to fix it.  . . .
    I would say that usually applies, but there are exceptions to that rule of thumb. As I said, if the values are in the code or a file, it will be impossible to correct the error while the program is running. But, if you have keyboard input, you might wish to catch the exception in a loop, until you get a correct input:-And that looks all right . . . at least until you realise there is a much better way: avoid that exception with a different sort of loop:-Of course the version with the while loop would probably have faster execution were it not for the fact that keyboard input is something like 1,000,000× slower than program execution.

    And now Stephan and I are in agreement that we aren't catching that unchecked exception.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Dave Tolls wrote:. . . For example all exceptions from Hibernate are RuntimeExceptions, similarly with Spring.
    The Files#newBufferedReader() method declares IOException, but the subsequent lines() method doesn't declare such an exception at all. The documentation comments tell the whole story.I don't think I have ever suffered an IOException, but the above code is not immune from crashing because of an IO error causing an exception to be thrown.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7963
    143
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Dave Tolls wrote:That only works if you are both in an environment where checked exceptions are not considered a Bad Thing, and are not using a framework where that view is held.

    Sure, I guess I'm referring to unchecked exceptions from the standard API, and in self-written code. I treat unchecked exceptions from frameworks you mentioned as if they were checked exceptions, and wrap them in checked exceptions if it's appropriate to propagate them.

    Campbell Ritchie wrote:But, if you have keyboard input, you might wish to catch the exception in a loop, until you get a correct input

    Like you pointed out in your second example, you can do this without catching exceptions.

    I have a class I use for console input:
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Do you really need a new Scanner in line 33? The version Rob Spoor taught me only needs one Scanner object:-That allows me to take advantage of Scanner's ability to read multiple ints in one line. My overloaded version for values in a certain range looks almost the same as yours, except that I throw an IllegalArgumentException if (!(max > min)) Otherwise, there is no risk of an exception.

    The version I have shown would not be thread‑safe. Obviously the loops with prompts are only suitable for input from the keyboard.
    OP: If you have input in GUIs with multiple text boxes or similar, you would have to verify the values of each text box whenever the submit button is pressed; that is a process similar to what we have been discussing, only it has to be done repeatedly. Also please find the logic error in my first post on this thread.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Steven Greenbaum wrote:. . . Wouldn’t an integer be of the wrong type?
    Yes, and no.

    A correct input is one which is the correct type and correct value, so it might be an integer between 1000 and 2000. There are two parts to that, type and value. But as Stephan told you, in a strongly‑typed language, the compilation process verifies the types and obviates the risk of your accidentally having the wrong type.

    It may be possible intentionally to pass the wrong type, but that is a different story.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 7963
    143
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Campbell Ritchie wrote:That allows me to take advantage of Scanner's ability to read multiple ints in one line.

    Yes, and that's exactly what I'm trying to avoid with my method. I want to ask for one value per line, and re-ask the question if the value is not valid. If there is a second question, I don't want to use values that the user entered before the question was posed.

    If I wanted to ask the user to enter multiple values in one go, I'd use a method closer to yours.
     
    Steven Greenbaum
    Ranch Hand
    Posts: 58
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thank you all your excellent and detailed responses. I am glad I have found the Moose community.

    I am working with a group of programmers in a foreign country. I sent them my project before adding the error checking. They have implemented it themselves and I have asked them to send it back when done because there will be may more use cases to add.
    I will ruminate on the many comments you and others have provided and proceed from there.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Steven Greenbaum wrote:Thank you . . .
    That's a pleasure
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Somebody pointed out to me that I missed a line out of the first loop I wrote in  this post; I didn't set needsReading to false anywhere.
     
    Campbell Ritchie
    Marshal
    Posts: 56525
    172
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Somebody gave me a cow and I have only just noticed. Thank you whoever it was
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!