-1

I'm sure I'm going to catch flack for this... but I'm coming from a language with no try/catch blocks and I'm learning about Java exception catching, and I'm having a hard time seeing how it's not just a lazy version of validation. I've seen a few examples like:

String Box [] = {"Book", "Pen", "Pencil"};
while(i<4)
{
    try
    {
        System.out.println(Box[i]);     
    }
    catch(ArrayIndexOutOfBoundsException e)
    {
        System.out.println("Subscript Problem " + e);
        i++;
    }

and:

int y = 0;
int x = 1;
// try block to "SEE" if an exception occurs
try
{
    int z = x/y;
    System.out.println("after division");
} 
catch (ArithmeticException ae) 
{
    System.out.println(" attempt to divide by 0");
}

These are obviously very rudimentary examples... but IMO either these are terrible examples of catching errors, or there's no good reason to do it. In example one if we loop for number of elements in Box we don't need to check for out of bounds indexing. In example two if we check for a divisor of 0, we don't need to check for that ArithmeticException.

Is there a good example or reason why using try/catch blocks is better than just good-old-fashion variable validation? or is it just the "Java" way?

Mike
  • 47,263
  • 29
  • 113
  • 177
  • 2
    What if you let the user input an array index? What about IO exceptions? – gefei Jan 04 '13 at 14:33
  • It's not just the "Java" way; many other programming languages support exceptions in the same way or similar to Java. – Jesper Jan 04 '13 at 14:34
  • 6
    (Opinion here) I would argue that both of those examples are poor for what exceptions are meant to do. Exceptions are *exceptional*, as in there was no reasonable way to check for these conditions first. – vcsjones Jan 04 '13 at 14:35
  • -1 voted to close as "not constructive" – Erick Robertson Jan 04 '13 at 14:35
  • 2
    These are really bad examples - good thing is: they show what you should not do! – assylias Jan 04 '13 at 14:35
  • @gefei I don't think that's an "exception".. in that case you should guard against it. I'm not sure but exceptions shouldn't replace control flow. – Lews Therin Jan 04 '13 at 14:36
  • 2
    Catch an exception only if you know how/can handle it, otherwise just let it propagate. – BigMike Jan 04 '13 at 14:36
  • These examples given are for understanding purpose and how to use exceptions – Nandkumar Tekale Jan 04 '13 at 14:36
  • @gefei - you know the size of the array by getting the length propriety, a check of user's input `>=` the length of the array will tell you if it's inbounds without needing a try/catch block. – Mike Jan 04 '13 at 14:37
  • @vcsjones - OK... so what's a good example? – Mike Jan 04 '13 at 14:38
  • @LewsTherin you might avoid ArrayOutOfIndexException by checking. but what do you do to avoid IOException? – gefei Jan 04 '13 at 14:39
  • @assylias - That's what I was thinking... but what makes them bad examples? What's a better example? – Mike Jan 04 '13 at 14:40
  • @BigMike - I'm not sure that answers my question. I'm asking *why* try/catch in the first place? What's an example of a reason for actually needing a try/catch of these are bad examples? – Mike Jan 04 '13 at 14:41
  • @ErickRobertson - I respectfully disagree. I require "specific expertise" to understand why/when we should use try/catch blocks. These are the examples I have right now and they don't show me anything. – Mike Jan 04 '13 at 14:43
  • 1
    @Mike indeed it is. You should use try/catch just when you ACTUALLY can handle the exception, catching an IOException upon opening a socket connection is good, you can retry or simply give up with a message. These examples are for the sake of writing a try/catch block, IMHO no real programmer would ever catch ArrayIndexOutOfBounds on a static array loop. – BigMike Jan 04 '13 at 14:46
  • @BigMike - OK... I haven't tried socket programming with Java yet, but I would have assumed the return from the `open()` call (or equivalent) would give a value of success or failure that could be validated rather than just blindly saying "try to use this and catch it if it fails". Am I incorrect? – Mike Jan 04 '13 at 14:57
  • @Mike If i recall correctly is a "void connect() throws IOException" so it won't give you an error code nor doing something like setting errno :D - still I miss those days. However if you come from C language, looking at exception handling of a socket opening example should be more meaningfull. – BigMike Jan 04 '13 at 15:04
  • @Mike See also: http://stackoverflow.com/questions/409563/best-practices-for-exception-management-in-java-or-c-sharp – assylias Jan 04 '13 at 15:19
  • @assylias - Thanks for the linke, there's some great information in there. Very helpful. – Mike Jan 04 '13 at 15:38

7 Answers7

6

This would be an example in a language without exceptions:

if (!rename(file1, tmpName))
  if (!rename(file2, file1))
     if (!rename(tmpName, file2))
        return 0;
return -1;

Also note that there will be no details on what exactly went wrong.

Compare with Java:

try {
   rename(file1, tmpName);
   rename(file2, file1);
   rename(tmpFile, file2);
   return true;
}
catch (IOException e) {
   e.printStackTrace();
   return false;
}

If rename properly stores the source and target names in the exception message, we'll know exactly where it went bad.

To sum up, advantages of the exception mechanism include the following:

  • allows you to declare a block of code that must succeed as a whole and any errors get equal treatment;
  • allows you to delegate all error handling to a single point in the application, the so called exception barrier;
  • the exception object stores vital debugging information.

Exceptions are a huge win and all modern languages have them.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
2

You have picked the worst examples since they are unchecked exceptions. If you see a lot of those types of try/catch blocks, I would tend to agree with you on the laziness/inappropriateness factor. However, for CHECKED exceptions, try/catch are extremely useful. Didn't you get bored in C doing

int status = thisStatementMayFail();
if (status > 0) {
    // do_stuff
}
else {
    // handleException();
}

I prefer Java's

try {
    thisStatementMayFail();
    // do stuff
} catch (Exception e) {
    // handleException
}

Could be lazy, but definitely better IMO.

xagyg
  • 9,562
  • 2
  • 32
  • 29
  • it's got a couple of upvotes, so must be a good answer. Your answer implies to me that both of these statements are equivalent, and try/catch doesn't ever really *need* to be used, but is just a different form of validation/error handling. Is that a fair assessment? – Mike Jan 04 '13 at 15:00
  • @Mike Yes, try/catch is a different form of error handling, however, note that because Java has a try/catch mechanism for handling exceptions, many methods and constructors rely on this mechanism (as they should) and don't explicitly return a value that you can check. So, in most cases the only sensible way to check if a method or constructor fails is by using try/catch. In some rare cases, you can still check values, for example, reading character by character through a stream will return -1 at the last char (EOF). Not necessarily an exception, but could be interpreted that way. – xagyg Jan 04 '13 at 15:06
1

I think exceptions are a type of error checking, but not lazy in any way.

The example that you have there can be lazy, but if you change it to something that makes a remote call and the remote call can fail for a number of reasons (network down, remote service failure etc), then checking the return code to see if there was an error (like it's done in C, with integer return codes) introduces extra complexity.

The idea behind exceptions is that they represent errors that cannot be recovered at the point where they are raised.

About catching ArithmeticException, I think that would be bad programming rather than lazy error detection for most cases (but not all... although I cannot think of one).

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • +1, I like your answer for the C example. That's pretty much what I was driving at, I can do anything well programmed in C (try, check returns, and retry if need be). I don't need these "blanket" try/catch blocks. But you're correct, it's more code and more complexity than just a `try`/`catch` – Mike Jan 04 '13 at 15:05
1

One of the main arguments for exceptions are that they progpagate outside the normal flow.

Using your example:

public String getMyData(int index) {
  String box [] = {"Book", "Pen", "Pencil"};
  return box[index];
}

What do you do in case index is 4? How will the code calling the method know that there is no valid value for this (and don't say "use null", because many methods may return null as a legal value).

That is the main utility of exceptions. Additionally, the hierarchy of exceptions serves to ease the handling of the situations by the methods that know how to handle it (in this example, the calling method may be happy with using the null value in case an exception has been thrown, or may feel that it has to stop the program).

SJuan76
  • 24,532
  • 6
  • 47
  • 87
  • Given this example I would expect the `getMyData()` method to validate the input: `if((index >= 0) && (index < box.length))` then if it's not valid have it return an "invalid" string, whatever it was predefined to be, and have the caller check for that. It seems to me this example is another one where a better defined interface would prevent the need for exception handling (ie if I pass something invalid here's the expected output) – Mike Jan 04 '13 at 14:53
  • And if there is no predefined "invalid" String? – SJuan76 Jan 04 '13 at 14:56
  • @Mike So you validate inside the function and then what? You will have to decide what to return as invalid value and the function caller will still have to account for the possibility of this invalid value. Doing it via exception throwing is hence already a more elegant way – Lucas Moeskops Jan 04 '13 at 14:56
  • In a case like this still I'd prefer to have an explicit "throws ArrayIndexOutOfBoundsException" on the signature of the method – BigMike Jan 04 '13 at 14:59
1

Try/catch in Java is more a mechanism to handle unforeseen (i.e., less common) errors and exceptions and propagate the programming context to the coding logic able to catch and handle that condition.

The examples you provide are indeed bad examples of try/catch and is basically lazy validation. Bad coding practices often catch exceptions with try/catch rather than with an if test.

try/catch has an overhead and is more expensive operation than an if-test such as you would use for your second example:

if (y != 0) {
  int z = x/y
  // use z value
} else {
  System.out.println(" attempt to divide by 0");
}

I/O offers a better example for exception handling. In most cases you can open a file, read its contents and close the file but occasionally the file is locked, does not exist, fails to close, etc. Rather than test ever possible condition that could go wrong with I/O you can use try-catch to handle an IOException or FileNotFoundException cleanly.

BufferedReader br = null;
try {
    File file = new File("target.dat");
    br = new BufferedReader(new FileReader(file));  
    String s;
    while ((s = br.readLine()) != null) {
          System.out.println(s);
    }
} catch (IOException ioe) {
    System.err.println("Error: " + ioe);     
} finally {
 if (br != null)
  try {
    br.close();
  } catch(IOException ioe) {
    System.err.println("Error: " + ioe);     
  }
}
CodeMonkey
  • 22,825
  • 4
  • 35
  • 75
0

Exceptions should only be used for exceptional circumstances -- things that simply should not happen during normal execution. They should only be caught you can actually do something about them.

In non-exceptional cases, such as validating external input, an if should be preferred. This is because exceptions are significantly slower than an if if they're thrown, but can actually be faster if they're not.

Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
0

Not all errors can be validated against before attempting the work. Example, can you detect a website will return a page until you actually try?

Without exceptions you have to have complex return types to report errors to the caller. And if you want to propergate the errors, these return types get ever more convoluted and complex.

Exceptions are a great way to propergate errors and unwind the stack. But that has to stop somewhere and that somewhere is where you need a catch.

weston
  • 54,145
  • 21
  • 145
  • 203