Week 7 Answers


  1. Modify the main code so that the line creating a new Person now reads:
                Person p = new Person("Person number " + i, (age - 50));
    
    What happens when you run the program now?

    You get a load of -ve ages in the list of created Persons

  2. Modify the "Person" code above so that the first constructor throws an "IllegalArgumentException" if the age parameter supplied is less than zero.

    Your constructor will now look like this:

        public Person(String name, int age, Color hair)
        {    
            if (age < 0) {
                throw new IllegalArgumentException("age too small");
            }
            
            this.name = name;
            .
            .
            .
    
    What do you expect will happen when you try to compile the program now?

    You might expect the compiler to complain about a missing "throw" clause on the constructor. It doesn't though, because IllegalArgumentException is a subclass of RuntimeException, and RuntimeExceptions don't have to be caught. Note that you could have a "throws" clause if you want, but you aren't required to.

  3. (If you've not already done so) add an exception handler to the program to deal with any "IllegalArgumentException"s that occur during main

    Your main loop will now look something like this:

            for (int i=0; i<20; i++) {
                // Create a new person with random age
                int age = (int) (Math.random() * 70);
                try {
                    Person p = new Person("Person number " + i, (age - 50));
                    myCollection.add(p);
                }
                catch (IllegalArgumentException e) {
                    System.out.println("Couldn't add person with age of " 
                                       + (age - 50));
                }
                
            }
    
    
    By limiting the scope of the try..catch block to a single iteration, you'll still get the +ve aged Persons in the list.
  4. Change the code so that instead of throwing an "IllegalArgumentException", it throws an "Exception". What do you expect to happen when you compile the program now?

    You'd expect the compiler to complain about uncaught Exceptions.

  5. Fix the program so that it builds and runs when the type of exception thrown is an "Exception"

    You'll need to change all the constructor definitions so that they say throws Exception and you'll have to change your try..catch block to catch Exception.

  6. Create a new class called a "SillyAgeException".

    Here's a minimal example (javadoc missing):

    public class SillyAgeException extends Exception {
        public SillyAgeException() {}    
    }
    
    

    Change your Person class so that it throws a SillyAgeException for minus ages

    Doing this means you'll should :

    • change the "throw" statement to say something like:
              if (age < 0) {
                  throw new SillyAgeException();
              }
      
    • You also should change all the "throws" clauses to say they throw SillyException. Note you don't have to do this here but it would be good practise - when using exceptions you should be as precise as possible.
    • Similarly, you should change the try..catch clause to catch SillyException
  7. Add methods to your SillyAgeException so that it keeps track of what the silly age was.

    Here's one way to do this:

    public class SillyAgeException extends Exception {
        int requestedAge;
        
        /**
         * The only constructor for this class, which requires that you
         * say what the silly age was
         */
        public SillyAgeException(int sillyAge) 
        {
            requestedAge = sillyAge;
        }
       
        /**
         * Return the age that was invalid
         */
        public int getRequestedAge() 
        {
            return requestedAge;
        }
        
        /**
         * Returns a message containing the silly age
         */
        public String getMessage() 
        {
            return "Age of " + requestedAge + " is silly!";
        }
    
        
    }
    
    
    In the Person code, catch any SillyAgeExceptions, and display a message reporting what the silly age was.

    Now you'll have to make sure that Person is catching SillyAgeException and not Exception everywhere, then your main loop will look like this:

            for (int i=0; i<20; i++) {
                // Create a new person with random age
                int age = (int) (Math.random() * 70);
                try {
                    Person p = new Person("Person number " + i, (age - 50));
                    myCollection.add(p);
                }
                catch (SillyAgeException e) {
                    System.out.println("Couldn't add person with age of " 
                                       + e.getRequestedAge());
                }
            }
    
  8. Add code to the "compareTo" method so that it throws a "ClassCastException" if it is called with an argument that is not a Person.

    The "compareTo" method will now look like this:

        public int compareTo(Object o) 
        {
            if (o instanceof Person) {
                Person other = (Person)o;
                if (other.age > age) {
                    return 1;
                }
                if (other.age < age) {
                    return -1;
                }
            }
    
            // The object wasn't a Person, or it was
            // a Person with the same age
            throw new ClassCastException("Not a person!");
    
            // Don't need a return statement here because we'll
            // never get this far
        }
    
    
  9. Use a "finally" clause in the main method so that it displays a message "the program is now finishing"

    Your main method will now look like this:

        public static void main(String [] args) 
        {
    
            try {
                java.util.LinkedList myCollection = new java.util.LinkedList();
            
                for (int i=0; i<20; i++) {
                    // Create a new person with random age
                    int age = (int) (Math.random() * 70);
                    try {
                        Person p = new Person("Person number " + i, (age - 50));
                        myCollection.add(p);
                    }
                    catch (SillyAgeException e) {
                        System.out.println("Couldn't add person with age of " 
                                           + e.getRequestedAge());
                        
                    }
                    
                }
                
                java.util.Iterator it = myCollection.iterator();
                while (it.hasNext()) {
                    Object o = it.next();
                    System.out.println(o);
                }
                System.out.println("The collection has " + myCollection.size() 
                                   + " elements");
                
            }
            
            finally {
                System.out.println("The program is now finishing");
            }
        }
    
  10. Modify the "main" method so that instead of creating 20 Person objects, it reads from the command line an argument containing the number of objects to create, e.g.
         $ java Person 25
    

    The "25" will be passed in as the first element of the "args" array. But since that is an array of Strings, you need to turn it into an integer, which you can do using a static method in the Integer class:

                int numObjects = Integer.parseInt(args[0]);
    
  11. Make the main method throw an exception if the user asks for more than 100, or less than 5 Person objects.

    You could do this:

                int numObjects = Integer.parseInt(args[0]);
                if ((numObjects < 5) || (numObjects > 100)) {
                    throw new IllegalArgumentException("choose between 5 and 100");
                }
                
    
    
  12. When do you expect the "finishing" message to be displayed if
    • The program finishes normally

      The very last thing before the command prompt

    • The program throws an exception because the user asked for 1000 objects?

      Depending on what kind of exception you're throwing:

      • If you're throwing a RuntimeException (as is the case in the sample above, where IllegalArgumentException is used), then the compiler won't make you have a "catch" clause. In this case, the exception will be propagated to the JVM after the program has exited. So you'll see the "finishing" message as your program terminates, followed by the exception message which the JVM will display when control passes back to it with the uncaught exception.
      • If you're throwing an exception which is not a RunTimeException, (e.g. if you just throw Exception), then you will be forced by the compiler to provide a catch clause (or have throws Exception on the declaration for main()). If you catch the exception yourself, then the "finishing" will be displayed after your catch block. If you don't catch it (i.e. let it be thrown to the JVM), then the "finishing" will be displayed before any exception message).

Back to index page