Never confuse education with intelligence, you can have a PhD and still be an idiot.
- Richard Feynman -



Chapter:Exceptions

From Juneday education
Revision as of 13:35, 17 October 2016 by Rikard (Talk | contribs) (What is an Exception: Answer to the questions for What is an exception?)

Jump to: navigation, search

Meta information about this chapter

Expand using link to the right to see the full content.

Introduction

Purpose

Goal

Concepts

Instructions to the teacher

Common problems

Videos

All videos in this chapter:

See below for individual links to the videos.

What is an Exception

Description

This section introduces the concept of an exception. An exception is a signal of your program's running into some situation which is not the normal case or what you hoped for.

You can think of exceptions as being of two types: Contingencies (eventualities which may occur but are not very normal) and failures which are when something goes very wrong.

A contingency is when something rare happens but we know that it could happen and should be prepared for it. If there is some rule in our system which is being broken, then we could use the exception mechanism of Java to signal that this rule was broken. If we think about that, passing information about this rule having been violated using an exception object, allows us to have a feedback mechanism from a method which doesn't use the return statement.

A method could have a return value for all normal conditions but when something rare happens, the method could instead throw an object of some exception type to the caller (the return statement would then never be reached and the method would not be possible to evaluate to any value - instead the caller would have to deal with the exceptional case that occurred).

This introduction also discusses in the video lecture that in Java, there are two main types of Exception objects. The first type is "checked exceptions" which are exceptions that a method could declare that it can throw, and that the compiler forces the calling code to handle using some special code (which we will show in a later lecture). A method which can "throw" an object whose type is a checked exception must either declare that it throws this exception, or handle it internally. If the method doesn't handle such exception and instead declares that they may be thrown from the method, any code which calls the method end up in the same situation.

If code in a method A calls method B, and method B is declaring that it might throw a checked exception, then the method A author must choose between two options: 1. Handle the exception which might be thrown by B, or, 2. declare that A too throws this exception.

These rules allow us to write code which "warns" for exceptional cases and force calling code to handle this or pass the problem on to some code which does handle it.

What could be a contingency exception (an eventuality which we know could happen but hope it doesn't)? Let's pretend we have a web shop which has some code for processing orders from the customers. The company has discovered that some orders look very suspicious and seem to come from the same customer but too quickly for being the result of a real human sitting in front of a web browser and actually placing the orders. The company then adds a business rule, that no two orders may be placed by the same customer within five seconds (because it must be a machine placing the orders rather than a human).

The method for processing orders must now obey this rule and check that an order is not placed by a customer who just placed an order less than six seconds ago. This should not be so frequent and could be considered a contingency. Let's further say that the method placeOrder(Order o) normally returns an int with the order number from the order database. How would we deal with the case of an order being denied because of the five second rule? We would declare that the method throws a checked exception. This would force the code calling processOrder(Order o) to write code which prepares for this situation. The processOrder(Order o) method would in turn have code which "throws" the exception if it finds that the rule is violated.

This all allows the code which calls processOrder(Order o) to focus on the normal case and getting the int signifying the order id from the order database. If the rule would be broken, the calling code includes code which will also deal with this exceptional case. The calling code would just deny and cancel the order, possibly giving the customer notice of this.

What about faults, then? Bad things which we expect (or hope) never will happen, is typically to be considered faults. Their reasons could be hardware failures, network problems (including some server being unavailable), or plain programming errors. These types of exceptional cases are often very hard to recover from. If a file is missing which we depend on, what could the program do about this? Nothing really. The program must notify the user but often that's all the program can do. If a failure depend on a programming error, it is probably best that the exception is logged (and sent to the developers somehow) and that the program exits gracefully. It could be argued that a buggy program is better off dying with the problem logged, than trying to keep running with a faulty state.

To give an example of when a program is better off dying because of a programming error, is when the program part which is saving critical data for the user can't save the data because of some programming error (the programmer forgot to initialize the variable holding the file name of the save-file, for instance). Rather than keeping running with the user thinking that her data is being saved in a safe place, the program should actually die with an error message (and the cause of the error logged for the developer so that they can fix the error!).

Videos

  1. What is an exception? Part 1 (eng TODO) (sv) (download presentation)
  2. What is an exception? Part 2 (eng TODO) (sv) (same PDF as above)

Exercises for what is an Exception

This section is more of a theoretical nature and we haven't learned enough syntax for coding exercises yet. But we have learned a little about the two main families of Exceptions - checked exceptions and runtime exceptions (unchecked). Enough to read about a class in the online documentation and look at a constructor which the documentation says throws an exception (i.e. that it might throw an exception).

So there are just two simple exercises for this section to warm you up (and to encourage you to read the documentation about the Java API classes!).

1

Let's look at the API which comes with your Java installation. Look at the documentation for the class Scanner (in the java.util package). Read the description of the class to understand what it is used for. Now, locate the description of the constructor which takes one single argument in the form of a File. What is the exception it is declared that this constructor throws? Is it a checked exception or a runtime exception?

Hint: If the exception class extends Exception and not RuntimeException, it is a checked exception. Follow the link to the exception class to see the inheritance hierarchy of this class.

2

Describe whith your own words, why you think the constructor from the previous question throws this specific exception type. It it didn't throw an exception, what do you think would happen?

Solutions

Expand using link to the right to see the full content.

1 - The Scanner constructor

The constructor in question (the one which takes a single argument of type reference to File) declares that it throws a FileNotFoundException. When we look at the documentation for this class of exceptions, we'll see the following inheritance tree:

java.lang.Object
  java.lang.Throwable
    java.lang.Exception
      java.io.IOException
        java.io.FileNotFoundException

This means that FileNotFoundException is an IOException, which is an Exception! We immediately see that it doesn't extend RuntimeException anywhere in the tree, so it must be a checked exception. Simple, eh? If it doesn't extend at any point RuntimeException, it is a checked exception.

2 - Why the throws thing?

We can't give you your own words, but we'll provide an example of a feasible answer explaining what would happen if the constructor didn't throw an exception when something is wrong.

The Scanner class is used to parse (analyze and interpret) text. The text might be connected to some file, which is the reason for this constructor to exist - we can create a new Scanner and give a file object reference as an argument to this constructor. The Scanner object would then use the file represented by the File object as the source to read and parse text from. Luckily for us, the constructor throws an exception of type FileNotFoundException if the File object represents a File which doesn't exist on our hard drive. This is actually a feature, because it indicates that the parsing (reading and interpreting text) from this file won't work, for the simple reason that the file doesn't exist. Rather than letting us create a Scanner believing that it can read from the file represented by the File object, it throws a checked exception so that we will have to react on this case, rather than trying to scan a file which isn't there.

Two main types of Exceptions

Description

First of all, it's important to understand that exceptions in Java are represented by ordinary Java objects. These objects are of some class extending the class Exception (which is a subclass to Throwable). Well, they ordinary objects as they may be, there's one thing about exceptions which make them stand out from other objects, from the Java language perspective. Exception objects can be thrown (typically from a method) and they can be caught (by code calling a method).

The Exception class has one subclass which stands for one family of exceptions called RuntimeException. Runtime exceptions behave just like any other exceptions in that they can be thrown and caught using the language constructs for this. All other exceptions (subclasses to Exception but not in the branch extending RuntimeException) are called checked exceptions.

What earns checked exceptions their name, is that a method which throws such an exception must declare that it does so. The compiler will impose some restrictions on code calling a method which declares that it throws (actually might throw) a checked exception. The compiler checks such code. The rule imposed by the compiler is that code calling a method which may throw a checked exception, must be in a method either declares that it too throws a checked exception, or it must handle the exception which might be thrown. Handling the case that an exception might be thrown is done by catching the exception and providing code which does something about the situation.

              Throwable
                 ^
                 |
             Exception

              ^       ^
              |        \
RuntimeException       "all other, checked exception classes"
      ^                                  ^
      |                                  |
"unchecked exceptions"              subclasses here are checked exceptions

Often the exception classes under RuntimeException, the unchecked exceptions, are exceptions which comes from some kind of programmer mistakes, like trying to divide an integer with zero, trying to use an object via a reference which is null or trying to type case an object to a class which it cannot be cast to.

Since programmers aren't mandated by the compiler to write code to handle such exceptions, when they are thrown from a method, the exception object propagates unhandled to the caller. Since the caller doesn't handle it (doesn't catch it), the exception keeps propagating to the caller of the caller etc until it either reaches a handler or reaches the main method unhandled. If not even the main method has a handler for unchecked exceptions, the program ends abruptly with an error message and the whole chain of calls, all the way from main down to the method where the problem occurred.

Imagine an application whose main method calls method a() which calls method b() which calls method c() and an unchecked exception is thrown from c(). Let's pretend that the mistake in c() was that the programmer for c() tried to use a reference which was null, to call an instance method. This doesn't work, of course, and a NullPointerException will be thrown from c() by the runtime system (the JVM). NullPointerException is a RuntimeException and thus unchecked. If there is no handler anywhere in the chain of method calls which handles also RuntimeExceptions, the exception thrown by c() will propagate all the way up to main and crash the program with something like this, as the error message:

Exception in thread "main" java.lang.NullPointerException
	at Program.c(Program.java:12)
	at Program.b(Program.java:9)
	at Program.a(Program.java:6)
	at Program.main(Program.java:3)

You can follow the call chain if you start at the bottom (this is also called a call stack). Main calls, a, which calls b, which calls c which throws a NullPointerException.

So, are unchecked exceptions bad, then? Wouldn't it have been better if NullPointerException had been checked, so that the programmers would have been forced by the compiler to write a handler? To answer that question, we must think about what went wrong and why, and what could we do about it in a handler?

Looking closer at the code when the program crashed, showed the following version of the method c:

static void c(String s){
  s.toUpperCase();
}

The programmer called s.toUpperCase() on a reference to a String (for some reason). The programmer did so, just assuming that the reference s was a reference to an actual String object and not null. Apparently, though, s was null and the call to toUpperCase() failed with a NullPointerException. Now, what could possibly a handler somewhere have done about this? If the handler were declared in the main method, for instance, it is probable that it couldn't really know what happened and where and what to do about it. It knows, however, that something went wrong. We know now, after looking at the code, that the cause of the problem was that someone didn't make sure the reference s wasn't null before using it as a reference to an actual String object.

In this, somewhat simplified and constructed, example, we saw that the problem was actually a bug which could have been fixed with an if-statement checking whether s was null before using s as a reference to a real String, and taken care of null in the else-clause. So actually, just because no one handled the exception and the program crashed with a stack trace (the call stack printout), we could locate the bug and fix it. We are not so sure, however, the the user running the program would make much sense of the error message printout.

Checked exceptions on the other hand, come with the rule that a method must declare that such an exception might be thrown, and that calling code must either handle it or also declare that it might throw an exception (and pass the problem and requirement of handling it up the chain to its callers). The compiler will make sure that some code somewhere handles (catches) the exception thrown by such a method.

When could we use checked exceptions then? Well, first of all, the Java standard API is full of methods which are declared to throw checked exceptions. If we want to use an object from some class in the API and some method in that object "throws" a checked (or several) exception, then we have no choice but to follow the rules imposed by the compiler.

Sometimes we will actually write our own classes for checked exceptions and use them for our own method declarations. Doing so will work as expected, we will pose the restrictions following the rules of "handle or declare that your method throws" on to users of our methods.

One use case for using checked exceptions is when a method might run into some contingency (eventuality). A contingency could be something which isn't exactly good or common (happens rarely) but isn't really a critical error either. In order to understand how exceptions could be used to signal contingencies, we might first want to know what happens when a method throws an exception.

In a normal program flow, when a method calls another method, the control of the program is temporarily moved to the called method. Only when that method exits (for instance using a return statement), control is returned to the calling method, which moves on to its next statement. But when a method throws an exception, execution immediately leaves the method, even if no return statements have been reached yet.

The only way for a calling method to structurally and orderly manage a situation where a call to a method throws an exception, is to have a handler. Otherwise, control and execution will leave also the calling method and the exception will "bubble up" the call chain (be propagated to the caller of this method).

If we go back to contingencies hand how we can use exceptions to signal that something unusual has happened, we can actually view the throwing of an exception as an alternative return path. The normal return statements can then be used to exit the method nicely with some value representing information back to the caller. But if something extraordinarily happens, we can use an exception instead. If it is a checked exception, we can be sure that this will be handled sooner or later, and thus the exception can serve as information bearer of the contingency.

For completeness, we'll mention here that many (most) of the checked exceptions thrown by methods in the Java API actually represent more severe events than merely contingencies. Some checked exceptions thrown by methods in the API include events such as a file missing, a file system error, or a Java class not being found (but needed to be loaded). These are pretty serious situations (depending on the context of course), but the authors of the API decided to make them checked exceptions anyway.

It is possible to have opinions on the choice of making serious problems as checked exceptions as it forces us to write handlers wherever we use these methods and even though there is often not much the program can do to recover from the case of e.g. a broken file system. But we (the authors) are of the opinion that it was indeed a good choice. Making even severe problems checked exceptions, forces us as programmers to prepare for the event that something bad like that actually can (and sometimes do) happen. It makes us write code which is prepared for the worst, so to speak, and at least we can handle it in the eyes of the user of our software in that we can catch the problem and formulate a more understandable error message to the user, than the normal stacktrace printout they would otherwise see.

If we really dislike the decision to make something really bad a checked exception, we could actually use a strategy to make things easier for our colleagues using our methods, if our methods must call API-methods which throw checked exceptions. The strategy is to let our method provide handlers for the checked exceptions from the API calls. In this way users of our methods aren't obliged to write handlers (as they would have been if we just declared that we throw checked exceptions too, instead of handling them).

But wouldn't information get lost about the potentially really bad thing which lead to the exception our method caught? Yes it would. So the solution to this problem, according to the strategy, is that our handlers actually wrap the checked exception inside a runtime exception we throw from the handler! Runtime exceptions thrown by us don't come with the requirement for our callers to handle-or-declare. This allows our callers to proceed and call us as if everything should work fine, but in the event of something bad happening, a runtime exception will get thrown at them. Since they don't handle runtime exceptions, it will propagate up the call chain. This allows our project to put an exception handler somewhere, which actually also handle runtime exceptions, and make the decision of what to do about it. It it is really bad, the global (or general) exception handler can make the decision to terminate the application in a controlled way.

Videos

  1. Two main types of Exceptions (download presentation) (same PDF for all videos below)
  2. Two main types of Exceptions part 1 (eng TODO) (sv)
  3. Two main types of Exceptions part 2 (eng TODO) (sv)

Exercises

No exercises yet, please be patient. The assignment 2 has some exception handling which you can look at until we have provided exercises.


Solutions

Expand using link to the right to see the full content.

  1. Bladiblah

Examples (with code) using exceptions

Description

This section deals with the syntax and code to use when dealing with exceptions. We'll show you the syntax for declaring that a method throws an exception, how to throw an exception and how to catch an exception in a handler. We'll also look at what an exception object is, how to create one and what methods an exception has for the handler who caught it.

Let's start with checked exceptions, because calling such a method will according to the rules force us to either declare that we too are in a method which throws an exception, or to write a handler catching the exception.

Stuff which typically throw checked exceptions in the API classes, is stuff which has to do with I/O (input/output) like opening files, reading from or writing to files. In fact, there's a whole family of checked exceptions dedicated to the problems which may occur with I/O, IOException and its subclasses.

If we want to open a file for writing, the API provides quite a few classes for us to do so. We'll look at two of them. If we want to write text to a file, we need some kind of object which is a writer with some convenient methods for writing such as println(). The PrintWriter class seems just right for us. So, in order to create a PrintWriter for a file, we must construct the PrintWriter providing an object which can write to a file. We'll use FileWriter to represent that object. This book doesn't cover file management techniques, so please be aware that this is just an example for you, to see how to deal with IOExceptions. The constructor for PrintWriter can take a FileWriter as argument, so we'll look at the constructor for FileWriter next. In the API documentation, we find this constructor for FileWriter which seems just right for our example:

public FileWriter(String fileName) throws IOException

That seems simple enough, just provide the file name, and we'll get an object which knows how to write to that file. It will fit perfectly for the constructor of our PrintWriter! What we decide to do, is this:

PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));

But there's this thing about the constructor declaration above. Did you notice the throws IOException part? It tells us that in order to call this constructor, we'd have to handle checked exceptions, in particular some kind of IOException. That shows us the syntax for declaring that a constructor or method throws some exception! Just add a throws clause to the declaration and specify the families of exceptions which may be thrown.

Ok, so back to our example. We need to create a PrintWriter, so we needed to create a FileWriter for its constructor. But the constructor says that it might throw some exception which we must handle somehow. Why is it doing this to us? Come, on, what could possibly go wrong when opening a file for writing? Actually quite a lot might go wrong! What if the String provided for the file name, is actually the name of a directory? That wouldn't be particularly easy to write to. And what if the file doesn't exist, so the FileWriter tries to create it, but the file system and operating system says that we are not allowed to do that for some reason? Or what if the file indeed does exist, but the file system and operating system doesn't allow us to write to it, because it is write protected or owned by some other user etc?

So we'd better be thankful for the heads up and decide how to handle such events. We have now learned the rules, and we don't want to argue with the compiler (it won't be convinced by us anyway), so we know what to do. Either we declare that our method where we want to open the file, also throws at least an IOException. Or, we have to handle the possible IOException which might be thrown by the constructor of FileWriter.

So let's look at the basic syntax for writing a handler. The technique is to put stuff which might throw an exception we'll handle in a block called a try-block:

try{
  stuffWhichMightThrowException();
}

If an exception occurs anywhere in the try block, execution will immediately jump to the end of the try-block, where we'll have our handler. The handler is written as a block called a catch-block (at least we call it that now):

try{
  stuffWhichMightThrowException();
}catch(ExceptionType e){
  // code that deals with the exception known in our handler as "e"
}

As you see, the catch-block starts with a pair of parentheses which declare a parameter of some exception type (which should match the exception we try to catch) and a parameter name for this exception, here e. As with any parameters, you can name it whatever you want, but we stuck with e for brevity. Inside the block of the handler, we can now use the exception object referred to by e in order to further investigate what has happened.

So, now it is time to talk a little about what an exception object (like the one we caught) is and what we can do with it! Like any object, it has a toString() method, which can be used for a textual representation of the exception, for instance if we want to log what happened to some error logfile. Additionally, exceptions have a few more methods, two of which we'll describe next. The getMessage() method, returns a String which may have a message for us. Perhaps the thrower created the exception, passing a message along to the constructor of the exception. If so, we can get the message by calling this method. Another interesting method which exceptions have, is the printStackTrace() method. This is a void method, which uses the standard error stream (in Java represented by System.err) to print the full stacktrace which lead up to the exception. This is also very useful for logging the root cause of the problem. Again, we'd like to remind you that stacktraces probably is better targeted towards programmers trying to understand and fix the problem, than towards the users of the program. It's good then, that it prints to standard error, which can be redirected and hidden from the user.

OK, so now, we have at least a few methods we could use on the exception we catch. We could then complete our handler for the construction of our PrintWriter to at least catch any exceptions and turn them into something more user friendly, as an error message. Note that this doesn't fix the problem at all, it just stops the exception from propagating up, potentially all the way to main, which might lack a handler too, which would make the program crash with a stacktrace!

static void writeFile(){
  try{
    PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
  }catch(IOException ex){
    System.err.println("Couldn't open file for writing: " +
                        ex.getMessage());
  }
}

On a side note, please notice that the try-block and catch-block both are written using indentation, consistent with the indentation for the method itself. We should use indentation wherever we are using blocks.

What would the output of this error handler look like, if an exception was thrown and caught?

$ javac WritingFile.java && java WritingFile
Couldn't open file for writing: OutFile.txt (Permission denied)

In the example output above, we see in action one of the things which might go wrong when trying to open a file for writing. In this case, we were not allowed to open the file. Perhaps it was owned by some other user.

What would a stacktrace have looked like? An example stacktrace for the same problem (if left unhandled) could have looked something like this:

java.io.FileNotFoundException: OutFile.txt (Permission denied)
	at java.io.FileOutputStream.open(Native Method)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
	at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
	at java.io.FileWriter.<init>(FileWriter.java:63)
	at WritingFile.writeFile(WritingFile.java:11)
	at WritingFile.main(WritingFile.java:6)

What would the syntax for our example method have been if we decided instead not to handle the IOException ourselves? According to the rules, we were allowed to declare that our method too throws an IOException, instead of handling it. We would use the same syntax as the constructor for FileWriter, actually!

static void writeFile() throws IOException{
  PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
}

So the syntax in this case goes throws IOException. What would the consequence of this decision be for the caller of our method? Let's for simplicity say that it is main which calls our method (as shown in the stacktrace ;-) ). According to the rules, it is now main which has the decision to either handle it or declare that it too throws an exception. Now, declaring that the main method throws an exception isn't very productive, because there is no one who cares and handles it. Declaring that main throws exception is sort of careless behavior, and on par with having a handler which only re-throws the exact same exception. So, we decide here that the author of main knows how to behave, and chooses to write a handler. The handler in main can use the same syntax as our handler did in the example above.

Now, the consequence of our decision to declare that our method throws IOException put some restrictions on the author of the main method. Whether this is a good thing or bad thing is up for debate. It is important that you understand, however, that these decisions on who to put the responsibility for handling exceptions, will be a topic for the project programmers meetings. Some will argue that the method which causes the exception should deal with it, so that they don't have to write handlers all over the place, just to call your method which should work most of the time just fine. Others will argue that it is a good thing that every caller is aware of the problems your method might run into. And, to make stuff worse for people trying to learn Java, others still will argue that there is a middle ground, a compromise we can use here.

This leads us back to the strategy we discussed in the previous section, where we caught an exception and re-threw it as some other exception (more precisely, re-threw it as an unchecked exception).

A very simple example of this middle ground goes something like this. First, the main method (or some method very close to main) should have a handler for all bad things that can happen but aren't handled elsewhere. This includes (at least some) runtime exceptions. Anything which might be thrown somewhere in the system could then be handled in a central place, where the appropriate measures can be taken. If it is convenient to let code call our method without the "burden" of writing handlers, our method could be written without a throws clause. But what about the IOException for the permission denied error, then? It must be handled by our method. Those are the rules. What our method could do then, is to catch the IOException and in the handler, re-throw it as some kind of runtime exception (which will only be caught by the central exception handler which could be in main, for instance).

Now, the people who'd complain about having to handle IOExceptions from your method would be pleased, since they don't have to do anything. And the people who are particular about knowing about problems your method might run into are pleased, because they get their handler in the main, and the handler there can be written to catch also the runtime exception you are throwing when you catch an IOException.

The following, oversimplified of course, example shows how your method could be re-written to catch the IOException and wrap it inside a RuntimeException together with a message:

static void writeFile(){
  try{
    PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
  }catch(IOException ex){
    throw new RuntimeException("Problem writing: "+ex.getMessage(), ex);
  }
}

The global handler in main (also very simplified, of course) could look something like this:

public static void main(String[] args){
  try{
    writeFile();
  }catch(Exception e){
    System.err.println("Something went wrong: " + e.getMessage());
    System.exit(1);
  }
}

The error message, if the global handler in main was put to work would then look like the following:

$ javac WritingFile.java && java WritingFile
Something went wrong: Problem writing: OutFile.txt (Permission denied)

Note that you now also got the basic syntax for throwing an exception! The keyword used was throw and the thing you throw is a reference to an exception object. The code in the example, threw a brand new RuntimeException, created on the fly.

Is it reasonable to throw runtime exceptions, since we do not get the help from the compiler to warn people that they might be thrown? Yes, of course it is. Why, of course? Because we don't keep secrets from the users of our objects and classes. If a public method might throw a runtime exception by the code we write, then we document that and make sure everyone who will call our method knows about this. Then it is up to them to ignore it or make sure there a handler further up the call chain.

An example of when it makes perfect sense to throw a runtime exception (and document it) is if we have a rule for some class, which says that some parameter is not allowed to be a null reference. Let's say that we have a constructor for a class Member (to create objects representing members of some association for a member system) which takes two parameters, name and email (both as String references). The rule says that the name parameter can never be null, or a NullPointerException will immediately be thrown by the constructor. We do this to prevent the system from ever creating a Member object whose name is null. The email, on the other hand, is not so important. Perhaps not every member has an email address even, so we allow our objects to have a null email.

The reasoning here, is that it is better that the system detects an attempt to create a Member with a null name and treat it as a programmer error, even if it leads to a program crash (or global handler terminating the program or so), then to hope that no code will do this by mistake.

The constructor could then look something like the below, if we accept that name and email are also instance variables of type String in the class:

public Member(String name, String email){
  // Name is NOT allowed to be null!!!
  if(name == null){
    throw new NullPointerException("Name cannot be null");
  }
  this.name  = name;
  this.email = email; // we can live with null emails ;-)
}

Of course it might seem a little drastic to throw a runtime exception from a constructor, but the fact is that this is not so uncommon at all. The only thing we have to keep in mind, is that this must of course be documented (and probably communicated to the programmers if they tend to forget stuff or read the documentation sparsely).

A quick search in the API source code for openjdk-7 shows that a NullPointerException is thrown at 550 places in the java top level package classes (classes in a package which starts with "java.").

If you want an alternative to the if-statement which is checking for null, there is a nice alternative in the Objects class, in the requireNonNull(T) method. It has two versions, one which takes an argument and throws a NullPointerException if it is null, and one that takes an argument and a String message and throws a NullPointerException if the first argument is null, and it sets the message passed as argument as the message of the NullPointerException. It can be used like this:

public Member(String name, String email){
  Objects.requireNonNull(name, "Name cannot be null");
  this.name  = name;
  this.email = email;
}

Any attempt to create a new Member with null as the parameter for name will result in a NullPointerException which left unhandled would result in a stacktrace similar to this:

Exception in thread "main" java.lang.NullPointerException: Name cannot be null
	at java.util.Objects.requireNonNull(Objects.java:228)
	at Member.<init>(NonNullExample.java:12)
	at NonNullExample.main(NonNullExample.java:5)

Finally in this section, we'd like to give you some advise. First, avoid to write a handler just be cause you "have to" and do nothing in the catch-block. This may sound self-explanatory, but it is sadly quite common practice not only among examples in literature and courses (often for brevity) but also among real programmers in the wild. It may solve a compiler error, but it will probably not handle the exception if you opt to do nothing when catching it. Second, try to avoid too broad Exception types in the catch-block. If you were to catch(Throwable t) you would catch every possible type of problem, regardless of whether it is an Error, Exception, RuntimeException or checked exception. It is probably not likely that you have a solution which fits every class of exception. So try to be precise and name as specific type of exception to catch as possible. It is legal to have several catch-blocks after each other, each catching a different family of exceptions. That seems like a good idea, if your try-block may set off many types of exceptions.

Videos

  1. Code and syntax for exceptions part 1 (eng TODO) (sv) (download presentation)
  2. Code and syntax for exceptions part 2 (eng TODO) (sv) (same PDF as above)
  3. Code and syntax for exceptions part 3 (eng TODO) (sv) (same PDF as above)
  4. Code and syntax for exceptions part 4 (eng TODO) (sv) (same PDF as above)

Exercises

No exercises yet, please be patient. The assignment 2 has some exception handling which you can look at until we have provided exercises.


Solutions

Expand using link to the right to see the full content.

  1. Bladiblah

Creating your own Exception using extends

Description

It is possible to create our own custom exception classes using inheritance. We have basically two options when doing this, extend RuntimeException and create an unchecked exception, or extending Exception and create a checked exception. The same reasoning applies to this choice as the one from the previous sections of this chapter. Checked exceptions force the caller of a method to handle-or-declare, while runtime exceptions are unchecked by the compiler (and might thus come more as a surprise for the caller). Review previous sections for a discussion about this.

Simply put, if you think the caller can recover from the situation which caused the exception, then you may use checked exceptions in order to make sure the caller prepares for this event. If you are pretty sure that the caller can't fix the situation anyway, it is possible to go with unchecked exceptions, and hope that there is a global handler which at least lets the application shut down gracefully if it is a really critical problem.

One reason for creating our own custom exceptions, is that we can wrap and hide the actual exception our class might run into. We can still throw an exception when something unwanted happens, but we can wrap it up in an exception which belongs to our package. This way, the client code (callers of our methods) doesn't have to know what the cause exactly is, and this has many benefits. First of all, we hide implementation details from the caller by using only our own exceptions. Second, the caller doesn't have to import the package where the original exception comes from, which is great, because if we change our mind later, then the caller is depending on this decision and might have to import some new exception from some new API, which is bad. Third, we can actually afford to be more specific about the problem if we use our own exceptions. Writing our own exceptions lets us name them in terms of the problem domain of our application, and not the domain of the API which caused the original exception.

Let's say, for instance, that we write a class which fetches objects and offers a method which returns a list of some objects to the caller. If these objects originally comes from a database, we can hide this fact from the callers, so that we can change our mind later. Also, there are quite a few exceptions which can be thrown when working with a database. Here are a few: BatchUpdateException, RowSetWarning, SerialException, SQLClientInfoException, SQLNonTransientException, SQLRecoverableException, SQLTransientException, SQLWarning, SyncFactoryException, SyncProviderException. Then there are of course also subclasses to these exceptions. Now, the caller of our method simply wants a list of objects, and the caller might accept that this at rare occasions doesn't work. But our bet is that the caller isn't so much interested in learning about the various exceptions connected to databases. We can here create our own exceptions with better names which fit better into the terminology of our application.

In order to extend Exception we simply use the extends keyword, as you would when extending any class. It is good if we provide at least two constructors for flexibility of our Exception class, and we can mimic two constructors from the superclass.

We suggest at least the following two constructors for our custom exception (Let's call the exception class OrderSecurityException):

public class OrderSecurityException extends Exception{
  public OrderSecurityException(String message){
    super(message);
  }
  public OrderSecurityException(String message, Throwable cause){
    super(message, cause);
  }
}

As you see, we call the constructors of the superclass Exception from our constructors, which passes along the parameters to the respective constructor of Exception.

The second constructors allow us to wrap some other Exception, if we'd want to do that.

We have shown you the syntax for wrapping exceptions in previous sections of this chapter and there is no point in repeating it here.

This section is mostly about syntax, so we will not go any deeper into the various choices we have leading up to design decisions for our custom exceptions. This will be covered in books about more advanced programming issues since this is an introductory Java book. This should come as a welcome surprise for you, because within the scope of this book, all you need to know about how to extend Exception (or RuntimeException) is stuff you already have learned from the chapter on inheritance!

The wrapping of another exception is also very uncomplicated business. You just create an exception using the operator new, and give a message parameter (as a String) as the first argument and a reference to the exception object to wrap as the second argument. Invoking a constructor and passing arguments shouldn't be new information either! We have created numerous objects this was so far in the course.

Videos

  1. Writing your own (eng) (sv) (download presentation)

Exercises

No exercises yet, please be patient. The assignment 2 has some exception handling which you can look at until we have provided exercises.


Solutions

Expand using link to the right to see the full content.

  1. Bladiblah

Some rules and syntax

Description

Finally (no pun intended), we'll give you some additional rules and syntax for working with exceptions. There's a whole lot more to learn if you are really interested in the links section at the end of the page as usual.

You can have more than one catch-block, each catching a different family of exceptions. This is encouraged, because if there can be more than one unrelated exception in the try-block, there is probably different ways to handle them. So rather than catching a broad superclass type exception, you are encouraged to write a catch-block for each type of exception which might occur in the try-block (if more than one).

try{
  // some code which might throw IOException
  // some code which might throw NumberFormatException
}catch(IOException ioe){
  // Handle I/O problem
}catch(NumberFormatException nfe){
  // Handle the fact that some text couldn’t be converted to a number
}finally{
  // If you need to, you can always add a finally clause
}

Sometimes, however, you have the same solution to more than one type of exception. Rather than repeating yourself, you can in such cases catch a list of exception types, separated by pipe (the vertical bar | ):

try{
  //Some code which can throw an SQLException
  //Some code which can throw an IOException
}catch(SQLException|IOException e){
  // Code which can handle both cases
  // (n.b. they should have the same solution if you do this!)
}

There are some rules when it comes to inheritance and overriding methods. If you extend a class and override a method from the superclass, then you cannot add exceptions to the method if none are declared to be thrown in the superclass version. And you cannot say that your overriding version of the method throws an exception which is broader than the exceptions that the superclass version throws. So you cannot declare that the overriding method throws an exception which is a superclass to the exception the superclass version throws.

The reason for this rule is quite simple and logical. Client code can have a reference to a superclass type and call some method. It must then know that the exceptions which are declared to be thrown by this superclass is all that it needs to write a handler for (or declare that it throws). It is quite common that the client code has a reference to some superclass and doesn't know what class the actual object the reference refers to is. So the compiler enforces that the object won't throw any broader exception than those of the method as declared in the superclass.

The last thing we'd like to tell you is a construct called try-with-resources. Please refer to the section above where we talked about the finally clause. One typical use for the finally clause is to close resources opened in the try-block. Closing a resource in the finally block, guarantees that it will be closed whether or not any exception was thrown.

The try-with-resources construct takes advantage of two interfaces, AutoCloseable and its subinterface Closeable. The AutoCloseable interface declares one single method, close(). Many of the classes dealing with resources (files, streams, connections) implement the AutoCloseable interface (or Closeable). Those who does, thus guarantees that they have a close() method which will close the resource.

The try-with-resources construct lets us skip the finally-block for such objects who have a close() method. The syntax is to put a pair of parentheses after the try and initialize the resource inside it. This will guarantee that the close() method is called, regardless of any exceptions (just like the case with the finally block). Here's a functioning program which uses this construct. The program reads the first line of text in its own source code and prints it to the standard out. It opens the source code file (the resource) and the try-with-resources construct guarantees that the file is closed, whether an exception happened or not.

import java.io.*;
public class Resources{
  public static void main(String[] args){
	String firstLine = getFirstLine();
	System.out.println("First line of this file: " + firstLine);
  }
  static String getFirstLine(){
	try( BufferedReader in = new BufferedReader
	      (new FileReader("Resources.java")) ){
	  return in.readLine(); // use the resource
	}catch(IOException e){
	  System.err.println("Couldn't open Resources.java");
	  return null;
	}
  }
}

Running the program will produce the following:

$ javac Resources.java && java Resources
First line of this file: import java.io.*;

Videos

  1. Some rules and syntax (eng) (sv) (download presentation)

Exercises

No exercises yet, please be patient. The assignment 2 has some exception handling which you can look at until we have provided exercises.


Solutions

Expand using link to the right to see the full content.

  1. Bladiblah

Links

External links

Books this chapter is a part of

Programming with Java book

Book TOC | previous chapter | next chapter