Exception dealing with in Java: The fundamentals



The FileInputStream(String filename) constructor creates an enter stream to the file recognized by filename. This constructor throws FileNotFoundException when the file doesn’t exist, refers to a listing, or one other associated downside happens. The FileOutputStream(String filename) constructor creates an output stream to the file recognized by filename. It throws FileNotFoundException when the file exists however refers to a listing, doesn’t exist and can’t be created, or one other associated downside happens.

FileInputStream supplies an int learn() technique to learn one byte and return it as a 32-bit integer. This technique returns -1 on end-of-file. FileOutputStream supplies a void write(int b) technique to jot down the byte within the decrease 8 bits of b. Both technique throws IOException when one thing goes improper.

The majority of the instance is a whereas loop that repeatedly learn()s the following byte from the enter stream and write()s that byte to the output stream, till learn() indicators end-of-file.

The strive block’s file-copy logic is straightforward to observe as a result of this logic isn’t mixed with exception-checking code (if checks and associated throw statements hidden within the constructors and strategies), exception-handling code (which is executed in a number of related catch blocks), and cleanup code (for closing the supply and vacation spot recordsdata; this code is relegated to an related lastly block). In distinction, C’s lack of the same exception-oriented framework leads to extra verbose code, as illustrated by the next excerpt from a bigger C cp utility (on this article’s code archive) that copies a supply file to a vacation spot file:

if ((fpsrc = fopen(argv[1], "rb")) == NULL)
{
   fprintf(stderr, "unable to open %s for readingn", argv[1]);
   return;
}

if ((fpdst = fopen(argv[2], "wb")) == NULL)
{
   fprintf(stderr, "unable to open %s for writingn", argv[1]);
   fclose(fpsrc);
   return;
}

whereas ((c = fgetc(fpsrc)) != EOF)
   if (fputc(c, fpdst) == EOF)
   {
      fprintf(stderr, "unable to jot down to %sn", argv[1]);
      break;
   }

On this instance, the file-copy logic is more durable to observe as a result of the logic is intermixed with exception-checking, exception-handling, and cleanup code:

  • The 2 == NULL and one == EOF checks are the equal of the hidden throw statements and associated checks.
  • The three fprintf() perform calls are the exception-handling code whose Java equal can be executed in a number of catch blocks.
  • The fclose(fpsrc); perform name is cleanup code whose Java equal can be executed in a lastly block.

Utilizing catch blocks to catch exceptions

Java’s exception-handling functionality is predicated on catch blocks. This part introduces catch and numerous catch blocks.

The catch block

Java supplies the catch block to delimit a sequence of statements that deal with an exception. A catch block has the next syntax:

catch (throwableType throwableObject)
{
   // a number of statements that deal with an exception
}

The catch block is much like a constructor in that it has a parameter listing. Nevertheless, this listing consists of just one parameter, which is a throwable kind (Throwable or one in all its subclasses) adopted by an identifier for an object of that kind.

When an exception happens, a throwable is created and thrown to the JVM, which searches for the closest catch block whose parameter kind instantly matches or is the supertype of the thrown throwable object. When it finds this block, the JVM passes the throwable to the parameter and executes the catch block’s statements, which may interrogate the handed throwable and in any other case deal with the exception. Take into account the next instance:

catch (FileNotFoundException fnfe)
{
   System.err.println(fnfe.getMessage());
}

This instance (which extends the earlier strive block instance) describes a catch block that catches and handles throwables of kind FileNotFoundException. Solely throwables matching this kind or a subtype are caught by this block.

Suppose the FileInputStream(String filename) constructor throws FileNotFoundException. The JVM checks the catch block following strive to see if its parameter kind matches the throwable kind. Detecting a match, the JVM passes the throwable’s reference to fnfe and transfers execution to the block. The block responds by invoking getMessage() to retrieve the exception’s message, which it then outputs.

Specifying a number of catch blocks

You’ll be able to specify a number of catch blocks after a strive block. For instance, take into account this bigger excerpt from the aforementioned Copy utility:

FileInputStream fis = null;
FileOutputStream fos = null;
{
   fis = new FileInputStream(args[0]);
   fos = new FileOutputStream(args[1]);
   int c;
   whereas ((c = fis.learn()) != -1)
      fos.write(c);
}
catch (FileNotFoundException fnfe)
{
   System.err.println(fnfe.getMessage());
}
catch (IOException ioe)
{
   System.err.println("I/O error: " + ioe.getMessage());
}

The primary catch block handles FileNotFoundExceptions thrown from both constructor. The second catch block handles IOExceptions thrown from the learn() and write() strategies.

When specifying a number of catch blocks, don’t specify a catch block with a supertype earlier than a catch block with a subtype. For instance, don’t place catch (IOException ioe) earlier than catch (FileNotFoundException fnfe). When you do, the compiler will report an error as a result of catch
(IOException ioe)
would additionally deal with FileNotFoundExceptions, and catch (FileNotFoundException
fnfe)
would by no means have an opportunity to execute.

Likewide, don’t specify a number of catch blocks with the identical throwable kind. For instance, don’t specify two catch (IOException ioe) {} blocks. In any other case, the compiler experiences an error.

Utilizing lastly blocks to scrub up exceptions

Whether or not or not an exception is dealt with, you might have to carry out cleanup duties, comparable to closing an open file. Java supplies the lastly block for this goal.

The lastly block consists of key phrase lastly adopted by a brace-delimited sequence of statements to execute. It could seem after the ultimate catch block or after the strive block.

Cleansing up in a try-catch-finally context

When sources have to be cleaned up and an exception isn’t being thrown out of a technique, a lastly block is positioned after the ultimate catch block. That is demonstrated by the next Copy excerpt:

FileInputStream fis = null;
FileOutputStream fos = null;
strive
{
   fis = new FileInputStream(args[0]);
   fos = new FileOutputStream(args[1]);
   int c;
   whereas ((c = fis.learn()) != -1)
      fos.write(c);
}
catch (FileNotFoundException fnfe)
{
   System.err.println(fnfe.getMessage());
}
catch (IOException ioe)
{
   System.err.println("I/O error: " + ioe.getMessage());
}
lastly
{
   if (fis != null)
      strive
      {
         fis.shut();
      }
      catch (IOException ioe)
      {
         // ignore exception
      }

   if (fos != null)
      strive
      {
         fos.shut();
      }
      catch (IOException ioe)
      {
         // ignore exception
      }
}

If the strive block executes with out an exception, execution passes to the lastly block to shut the file enter/output streams. If an exception is thrown, the lastly block executes after the suitable catch block.

FileInputStream and FileOutputStream inherit a void shut() technique that throws IOException when the stream can’t be closed. For that reason, I’ve wrapped every of fis.shut(); and fos.shut(); in a strive block. I’ve left the related catch block empty for instance the frequent mistake of ignoring an exception.

An empty catch block that’s invoked with the suitable throwable has no strategy to report the exception. You would possibly waste a number of time monitoring down the exception’s trigger, solely to find that you can have detected it sooner if the empty catch block had reported the exception, even when solely in a log.

Cleansing up in a try-finally context

When sources have to be cleaned up and an exception is being thrown out of a technique, a lastly block is positioned after the strive block: there are not any catch blocks. Take into account the next excerpt from a second model of the Copy utility:

public static void primary(String[] args)
{
   if (args.size != 2)
   {
      System.err.println("utilization: java Copy srcfile dstfile");
      return;
   }

   strive
   {
      copy(args[0], args[1]);
   }
   catch (IOException ioe)
   {
      System.err.println("I/O error: " + ioe.getMessage());
   }
}

static void copy(String srcFile, String dstFile) throws IOException
{
   FileInputStream fis = null;
   FileOutputStream fos = null;
   strive
   {
      fis = new FileInputStream(srcFile);
      fos = new FileOutputStream(dstFile);
      int c;
      whereas ((c = fis.learn()) != -1)
         fos.write(c);
   }
   lastly
   {
      if (fis != null)
         strive
         {
            fis.shut();
         }
         catch (IOException ioe)
         {
            System.err.println(ioe.getMessage());
         }

      if (fos != null)
         strive
         {
            fos.shut();
         }
         catch (IOException ioe)
         {
            System.err.println(ioe.getMessage());
         }
   }
}

The file-copying logic has been moved right into a copy() technique. This technique is designed to report an exception to the caller, nevertheless it first closes every open file.

This technique’s throws clause solely lists IOException. It isn’t vital to incorporate FileNotFoundException as a result of FileNotFoundException subclasses IOException.

As soon as once more, the lastly clause presents a number of code simply to shut two recordsdata. Within the second a part of this collection, you’ll study concerning the try-with-resources assertion, which obviates the necessity to explicitly shut these recordsdata.

In conclusion

This text launched you to the fundamentals of Java’s conventional exception-oriented framework, however there’s rather more to understand. The second half of this tutorial introduces Java’s extra superior exception-oriented language options and library varieties, together with try-with-resources.

Recent Articles

Related Stories

Leave A Reply

Please enter your comment!
Please enter your name here