51

Is it a good way to try something useless just to see if a particular exception is thrown by this code ?
I want to do something when the exception is thrown, and nothing otherwise.

try {  
    new BigDecimal("some string"); // This do nothing because the instance is ignored  
} catch (NumberFormatException e) {  
    return false; // OK, the string wasn't a well-formed decimal  
}  
return true;

There is too many preconditions to test, and the constructor BigDecimal() is always checking them all, so this seem the simplest method.

Clément
  • 729
  • 6
  • 18
  • 15
    It's good that you asked about this. It means that you recognize that this pattern is to be avoided, but you couldn't see another option. +1 – Erick Robertson Sep 10 '10 at 11:51
  • It's not an answer to the question, but your example is a superb memory leak... there may be cases where exception is used as the return of a function, but not where you should forget the return of new. – kriss Sep 10 '10 at 16:43
  • @Martin: Yes, you're right. I was inattentive and thought it was C++ instead of Java that has Garbage Collection. – kriss Sep 10 '10 at 19:30

10 Answers10

49

Generally, this practice should be avoided. But since there is no utility method isValidBigDecimal(..), that's the way to go.

As Peter Tillemans noted in the comments, place this code in a utility method called isValidBigDecimal(..). Thus your code will be agnostic of the way of determining the validity, and you can even later switch to another method.

Boris Pavlović suggested an option to check that using a 3rd party library (commons-lang). There's one more useful method there, which I use whenever I need to verify numbers - NumberUtils.isNumber(..)

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 12
    +1, especially if you encapsulate it in a nice little function with a meaningful name!lie isValidBigDecimal) so it can be easily exchanged when a better technique comes along. – Peter Tillemans Sep 10 '10 at 11:11
  • 2
    Such little utility methods are quite handy when implemented as C# extension methods. –  Sep 10 '10 at 15:32
30

If you dislike having a method like this one, try using BigDecimalValidator from Apache Commons Validator. In case of an invalid input String it returns null.

Boris Pavlović
  • 63,078
  • 28
  • 122
  • 148
  • I'd lean towards the Apache Commons if performance is a concern; it takes a bit longer to instantiate the exception and throw it than it does to simply check if something is valid. – Dean J Sep 10 '10 at 16:42
  • 1
    Even without considering the performance hit, I avoid using try/catch for logical tests, because it muddies the waters in the debugger. I don't know how it is in your favorite Java debugger, but in Visual Studio, I usually run in the mode where the debugger breaks on any exception. Exceptions that are thrown in "normal" situations and expected to be caught as part of the program logic become a nuisance. Too bad Microsoft doesn't follow this advice in various parts of the .NET framework implementation. – vanmelle Sep 10 '10 at 21:44
6

There's nothing wrong with doing this; after all, proponents of a certain other language are fond of saying "it's easier to apologise than to ask permission", that is, it's easier to wait for something to fail and deal with it than it is to avoid failure altogether. In this case, since there is no alternative, absolutely go for it.

Jon Purdy
  • 53,300
  • 8
  • 96
  • 166
  • There is an alternative - write a BigDecimal validator that returns false if the decimal passed is not valid. See also Boris's reply. Usually, checks /should/ be `if (x == valid) doSomething`, and the format `try x catch y` where some logic (like returning false) is found in the catch block should be avoided. – cthulhu Sep 10 '10 at 14:09
  • There's always more than one way to do it. – Dean J Sep 10 '10 at 16:42
  • @Erick: Well, I guess I get what I get for pretending to like Python a little more than I really do for five minutes, though I'm lost as to where you think there's any negativity, however "veiled" it may appear. @Cthulhu: When I posted my answer, I was under the impression of the OP that there was no simpler alternative. @Dean: Right you are. – Jon Purdy Sep 10 '10 at 22:17
5

Performance might not be great and the syntax verbose, but the code is very precise about what it does. There is no duplication between check and use, which is always a big concern.

(Note, this particular sort of conversion to and from strings is really for debugging and internal configuration. It doesn't handle locales and other human-oriented consideration. Use in file formats and wire protocols introduces a strong dependency to the representation used by the class.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • 1
    Actually, the performance difference between preconditions (check for valid input, then execute) and exception handling (execute, catch exception when input is invalid) is almost equal, especially if the input is correct in the majority of cases. This is, of course, debatable. – cthulhu Sep 10 '10 at 14:10
  • 1
    @Cthulhu If every case is a happy case, it'll probably be faster. At least until some tries a DoS on your server. *Performance for sad case is Bad.* Though unlikely to be a problem if it is a real human typing. – Tom Hawtin - tackline Sep 10 '10 at 14:24
  • 1
    Tom: Have you tried it? The last time somebody asked about this, the try/catch case was actually faster than the pre-validation case. – Gabe Sep 10 '10 at 16:21
  • @Gabe I believe you are confusing this with the case of exception generated by the JVM, which may be optimised away. For exceptions generated by library code this will not happen (although it is theoretically possible). – Tom Hawtin - tackline Sep 12 '10 at 12:36
  • Tom: By all means, prove me wrong. The case I remember had somebody who wanted to validate a `float` and the running the regex to validate it was slower than just handling the exception. – Gabe Sep 12 '10 at 14:01
  • @Gabe I am not going to waste my time with something you misremember. If you're really sure, I suggest writing a microbenchmark yourself, or even just finding your original source. – Tom Hawtin - tackline Sep 13 '10 at 09:37
  • Tom: If you haven't tried it, all you're doing is passing on superstition. BTW, the benchmark I saw was here: http://stackoverflow.com/questions/3133770/how-to-find-out-if-the-value-contained-in-a-string-is-double-or-not/3134533#3134533 The upshot was that the 250-character regex was only a couple microseconds faster than catching an exception -- hardly worthy of being called *Bad Performance*. – Gabe Sep 13 '10 at 21:05
  • @Gabe Thanks for finding the original source. `java.util.regex` as currently implemented in the Sun/Oracle Java library doesn't have great performance. In the cited benchmark, the regex comes out over twice as fast. Without regexs, running an equivalent of the code in the `BigDecimal` constructor without exceptions is hundreds of times faster, unsurprisingly. Construction exceptions in code is expensive. **Bad Performance** (in general in situations where it is done excessively). No superstition. – Tom Hawtin - tackline Sep 13 '10 at 22:58
  • Tom: The link I posted showed that you can throw hundreds of thousands of exceptions per second, which I do *not* consider to be **Bad Performance**. The link *does not* say that the constructor is hundreds of times faster when exceptions aren't thrown, so please tell me how you know this statistic. – Gabe Sep 14 '10 at 01:53
4

There's two known method to "check" preconditions.

LBYL : Look before you leap

This coding style explicitly tests for pre-conditions before making calls or lookups. This style contrasts with the EAFP approach and is characterized by the presence of many if statements.

EAFP : Easier to ask for forgiveness than permission.

This common coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

EAFP is always a good idea for language that have duck typing.

It clearly depends on what you want to do... If you are not sure of the kind of the object to manipulate, use EAFP.

ohe
  • 3,461
  • 3
  • 26
  • 50
1

Yeah this certainly is in contention with the Pragmatic Programmer notion of "Exceptions for exceptional cases" but you recognize what you're doing so there's no problem IMO

brown.2179
  • 1,750
  • 1
  • 12
  • 15
1

A comment on kriss' answer: I don't see a "superb memory leak" here. There is no reference to the created BigDecimal. As soon as this method completes, and we go out of scope, the object is eligible for garbage collection.

Memory leaks occur when we hold references we no longer need so the object can't be garbage collected.

gfidler
  • 11
  • 1
1

Try / Catch blocks should never be used for logic.

Chris Ballance
  • 33,810
  • 26
  • 104
  • 151
  • 4
    And the word "never" should NEVER be used so emphatically and absolutely when talking about programming style. – Tesserex Sep 10 '10 at 18:44
  • @Tesserex When should Try / Catch blocks be used for logic? – Chris Ballance Sep 10 '10 at 19:35
  • 1
    @Tesserex it has nothing to do with style, everything to do with performance. If your application isn't so big you can afford to be lazy and use exceptions to avoid properly handling data, then go for it. – Rex M Sep 10 '10 at 20:31
  • Rex's comment is the answer to yours. And so is the highest voted answer to this question. – Tesserex Sep 10 '10 at 20:47
0

Sure, why not. This is what we do to check if an email address specified by the customer is properly formatted:

try
{
    MailMessage m = new MailMessage(from, to, subject, body);
    return true;
}
catch(SmtpFailedRecipientsException ex)
{
    return false;
}

Now, people may argue about the performance or appropriateness of the structure, but they forget the trade-offs in simplicity:

  • Above code will trap the EXACT data formats accepted by .NET. Anyone who has parsed email addresses will know that there's a lot of variance about what's considered a properly formatted email address structure. This code guarantees to validate email address structures the way that .NET likes, not the way that I think it should be.
  • The exception traps multiple use-cases, not just the correctness of a basic data structure. It will validate multiple users in the CC, BCC and TO fields, which starts to get unwieldy to do with handwritten code.

As others discuss above, this code is best abstracted into a separate utility class rather than mixed in with your main code.

nobody
  • 19,814
  • 17
  • 56
  • 77
Simon at LabSlice-com
  • 3,017
  • 3
  • 24
  • 29
0

You have to consider that the construction of the Exception object is expensive in terms of time and resources for the JVM, because it has to construct the strack trace.

So what you propose is an easy but resource-consuming way to solve the problem.

So wether this solution is acceptable or not depends on the use you are going to give to this function, and your efficiency requirements.

Mr.Eddart
  • 10,050
  • 13
  • 49
  • 77