For this section, you'll need your Circle, Room, and Time classes.
Up until now, our mutator methods perform validation by using the conditional operator or if-statement to assign a default value to the instance variable. A more professional way of handling this problem is to inform the programmer using our class that they've tried to place an invalid value into an instance variable. You might think this could be done in the following way:
public void setRadius(double radius) { if (radius <= 0) System.out.println("Invalid value for radius!"); else this.radius = radius; }
The problem with this solution is that we're forcing the programmer to use the console. Similarly, we can't use JOptionPane's input dialog or we'll be forcing the programmer to use a GUI environment. The whole point of designing object-oriented programs is to write classes that can be used in any environment, whether it be command-line, GUI, or applet. If our classes use the console or dialog boxes, we limit the flexibility and usability of our classes.
Another solution might be to have the method return a string with the error message, but not only would that violate the rules regarding the format of mutator methods, but it would also mean the programmer would have to always use an if-statement to check to see if the method returned an error message.
A better solution is to have the method throw a special exception object called an IllegalArgumentException when the instance variable receives an invalid value. The IllegalArgumentException is a child of the RuntimeException class (which in turn is a child of the Exception class). If you check the docs for the IllegalArgumentException, you'll read that this exception class is used when "a method has been passed an illegal or inappropriate argument." We can use this exception class in our own classes by using the throw statement:
if (radius <= 0) throw new IllegalArgumentException("Invalid value for radius."); else this.radius = radius;
This new statement says "throw an IllegalArgumentException with the error message I've specified if radius is less than or equal to 0". If you guessed that the new operator indicates that we are instantiating a new IllegalArgumentException object and then throwing that object, then you were correct!
If you prefer, you can do the validation and exception throwing in two statements:
if (radius <= 0) { IllegalArgumentException myEx = new IllegalArgumentException("Invalid value for radius."); throw myEx; } else { this.radius = radius; }
Either way you do it, your mutator method setRadius() is now throwing an exception if the radius parameter contains an invalid value.
The exception objects in Java all have an instance variable called "message". When you pass a String value into the exception object's constructor method (as we're doing in both examples above by passing the string "Invalid value for radius." into the IllegalArgumentException constructor), the constructor method will place that string into the exception object's message instance variable. This will come in handy when a programmmer is using your class in a program:
Scanner keysIn = new Scanner(System.in); try { System.out.print("Enter a radius: "); int radius = keysIn.nextInt(); Circle circle = new Circle(radius); System.out.println("Area: " + circle.getArea()); } catch (Exception ex) { System.out.println(ex.getMessage()); }
In the sample code above, the programmer decided to use a try-catch block to handle the IllegalArgumentException that might be thrown if the user enters an invalid radius (and that will also catch the InputMismatchException if the user types a value that's not a valid int!) In the catch-block, the value of the exception object's message data member is displayed on the console.
Even though this catch-block's parameter is an Exception object, it will still catch both an IllegalArgumentException and an InputMismatchException. This is because of inheritance: both exception classes are child classes of the Exception class. You'll learn more about inheritance and catching multiple types of exceptions in the term 2 Java course, and in Chapter 18 of your textbook.
Modify your Room class to use exception handling for the length and width instance variables. Test your mutator methods in a program.
Modify the Time class in the same way: have the mutators throw exceptions instead of setting default values. Test your class in a program.