• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Which has a better performance, Exception or Optional?

 
Ranch Hand
Posts: 47
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hello,

I tried to find an answer online to find out, which performs better: Exception handling or using Optional instead? I have a real-world scenario from a Spring application:



Or using Exceptions:


After writing the code for Exceptions I thought that this is not a very good example. But just think of JavaEE instead where you don't just get Optional returned. This is not about the style itself, but rather on the performance, since I've heard people arguing Exceptions are better and some say Optionals are better.

Which ones may perform better?

Thanks and best regards
 
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Catching NPE is (almost) never a good idea. At least perform a null check.

Let's make your example a bit better. Assume that UserRepository.getById throws an EmptyResultDataAccessException if no match could be found.

As far as performance is concerned, it would surprise me very much if the exception example is not slower. With Optional, the additional overhead is an extra object (the Optional). With an exception, you also have an extra object (the exception). However, that includes a call to Throwable's fillInStackTrace method; this is called from all but one of the Throwable constructors. I've seen firsthand that using exceptions for flows can be horribly slow, and my guess is that this call is the reason.
 
Saloon Keeper
Posts: 10705
86
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Exceptions tend to be abused. They are supposed to be reserved for "exceptional" cases, cases that during normal execution should never happen. Having a method that searches for something and may or may not find it, is not exceptional. Exceptions should not (in general) be used for flow control.
 
Bartender
Posts: 1357
39
IBM DB2 Netbeans IDE Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:Exceptions should not (in general) be used for flow control.



That's interesting. What do you mean for flow control ? I've wrote at least a dozen of REST API, all of them following this pattern:

- check phase : check if parameter passed are valid, if not throw a proper exception;
- business logic execution: execute business logic and throw exception only if an unrecoverable error is met.

For example, one of such APIs executes reservations of goods in a warehouse to a given customer order. During the check phase, my API throw an exception, for example, if an already fullfilled order is passed as parameter.
To be honest, I don't think - but I could be wrong, of course !! - that doing so were a bad practice. Instead, localizing all formal controls (i.e like the check if given order is valid or not) at the very beginning of my API led me to write more clear code.
What am I missing ?
 
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
To continue from what Rob and Carey said:-
Don't think about performance first. Performance should be your last consideration, and then only if somebody complains your program s slow. As Rob and Carey said, it is a case of which technique correctly implements your requirements. I would think that Optional would be better, because it allows you to avoid nulls. Anyway, I am seeing things I didn't see in the old Sun style guide. When I see...my mind immediately goes to the style guide and I change that toBut then I see you are using Optional#isPresent(). That makes me think there has to be an elegant way to do it. Let's assume that the method called in line 7 uses Optional#ofNullable(), otherwise finding a null in line 8 would be impossible. Let's assume you can't change the method called from line 7 at present. So, if you get true from the isPresent() call, do you need to do more than change the state of that object? It is the same object in the Optional and in the repository. All you need to do is change the name. Can you obviate the compiler error for having two variables in scope both called user simply by setting the name? If not, you seem to have a method doing several things simultaneously, which sounds like a bad idea. You are getting a User reference from the repository, getting its value from the Optionsl, changing its name to the same as another User and saving the original User.
 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Claude Moore wrote:

Carey Brown wrote:Exceptions should not (in general) be used for flow control.



That's interesting. What do you mean for flow control ? I've wrote at least a dozen of REST API, all of them following this pattern:

- check phase : check if parameter passed are valid, if not throw a proper exception;
- business logic execution: execute business logic and throw exception only if an unrecoverable error is met.

For example, one of such APIs executes reservations of goods in a warehouse to a given customer order. During the check phase, my API throw an exception, for example, if an already fullfilled order is passed as parameter.
To be honest, I don't think - but I could be wrong, of course !! - that doing so were a bad practice. Instead, localizing all formal controls (i.e like the check if given order is valid or not) at the very beginning of my API led me to write more clear code.
What am I missing ?


Throwing an exception is good for exceptional cases, but I've seen too many cases of abuse. The worst one is this (fortunately, it's a theoretical case from Effective Java):


A rule of thumb is, if you can prevent an exception by performing a test, always do so.

Unfortunately, in some cases such a test is not possible. If that's the case you're stuck with catching the exception. A good example is Integer.parseInt (and similar methods). Sure, you can check the format, but only digits still does not guarantee a valid int. Ideally there would be method OptionalInt Integer.tryParseInt(String s). This would allow you to do the following:

(I've even written a patch to add both Integer.tryParseInt and Long.tryParseLong, with overloads. However, when I first submitted a patch to add missing map methods to OptionalInt, OptionalLong and OptionalDouble, Brian Goetz said that Oracle is "currently trying to avoid adding anything to OptionalInt/Long/Double, because our current plan is to replace these with a specialized Optional<int> once Valhalla delivers". That made me put the patch on hold, so I can write an Optional<int> version instead. I'm thinking about creating a separate library instead that can be used until that time comes.)
 
Rob Spoor
Sheriff
Posts: 22783
131
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
By the way, I agree with Campbell on using isPresent(). If you're going to use that, you might as well use null instead.

The following would be an alternative. I just dislike the change to the user inside the map method...
 
Campbell Ritchie
Marshal
Posts: 79180
377
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If a method throws an IllegalArgumentException, that isn't flow control. That is the method refusing to run at all, because of incorrect input, and throwing an exception to notify that to its caller. That is perfectly all right. It is different from what Rob is talking about.
 
Christian Wansart
Ranch Hand
Posts: 47
IntelliJ IDE Firefox Browser Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for all the interesting answers.

I prepared an example: https://github.com/cwansart/javaee-exceptions-test

This is how I learned to deal with issues, like not finding elements in the database. In the Resource I catch the NoResultException.

In other projects we (me and other devs) threw a lot of Exceptions on services and repositores, like CustomerNotFoundException, WrongPasswordException, DefaultLanguageNotAvailableException which were caught on the resource to create error messages or default values.

After reading and thinking about those things, I'd say that's kind of flow-control. That is why I was wondering if this is a good idea.

Thanks
 
Carey Brown
Saloon Keeper
Posts: 10705
86
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I couldn't find where you were throwing exceptions in your git link.

One thing I do with most queries is to loop through the result set adding data transfer objects created from the results to a list. Then I return the list.

The application can look at the list.size() to see:
  • 0 == not found (may be an error?)
  • 1 == found
  • > 1 several found (may be an error?)
  •  
    Christian Wansart
    Ranch Hand
    Posts: 47
    IntelliJ IDE Firefox Browser Java
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    In my linked example the query may throw an exception. The other exceptions were examples from other projects I attended. Let's say we have a user who types in a wrong password, I used to check whether the password is correct or wrong and throw an exception. I would catch that in my resource class like I did with NoResultException.

    UserResource.java




    So my issue is that the API kind of forces me to use Exceptions. I've learned to catch those and re-throw more meaningful exceptions and catch them in the resource.

    @Carey Brown: so you use integers instead of exceptions to create handle different situations?
     
    Carey Brown
    Saloon Keeper
    Posts: 10705
    86
    Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
    • Likes 1
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Christian Wansart wrote:@Carey Brown: so you use integers instead of exceptions to create handle different situations?


    I still use exceptions for some DB stuff, including logins. I was just illustrating that, at least with queries, there are other ways of delegating error decisions to the application rather than making those decisions at the DB level. And I was not returning an int, I was returning a list that may contain any number of entries, including zero. Then the app can make the determination as to what constitutes an error.
     
    Ranch Hand
    Posts: 127
    2
    Monad Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    One thing to consider... I one important thing. The Optional solution is type safe.
     
    Consider Paul's rocket mass heater.
    reply
      Bookmark Topic Watch Topic
    • New Topic