I have 2 examples:
void terminate(String x) {
System.exit(0);
}
void x (long y) {
if(y == null) {
terminate();
}
//code
}
.....
x(null); //Don't want that
This example seems to work. I want to make sure that long y is not null. I might do this instead:
void x (long y) throws NullPointerException {
//code
}
...
try {
x(null);
} catch (NullPointerException e) {
e.printstacktrace();
}
What would the difference in performance be? In such example, it might not be visible, but in a complex program, would it matter? Should I get into practice of exceptions instead of if then?
Use exceptions for exceptional circumstances, when things happen that youdid not expect and where nothing sensible can be done to recover.
Otherwise, use if-then and maybe return a status code.
In terms of performance, exceptions create a huge overhead compared to returns. Calling a method and catching an exception if it didn't work is verbose and annoying.
void myOperation() {
step1();
step2();
step3();
}
In this example, exceptions are preferable for when any of the steps fails, the entire operation fails anyways, so I prefer not having to deal with any of this.
void myOperation(String number) {
int n;
try {
n = Integer.parse(number);
} catch (NumberFormatException e) {
n = DEFAULT;
}
doThings(n);
}
In this case, having to catch the exception is annoying because I kind of expect the string to be invalid and have a reasonable alternative. The exception makes the code slow and verbose.
What would the difference in performance be?
Version with exception definitely will works slower and will have overhead of processing exceptions, creating objects, filling stack traces and so on.
In such example, it might not be visible, but in a complex program,
would it matter? Should I get into practice of exceptions instead of if then?
In complex programs none use this kind of processing possible null pointer exceptions, and it's actually anti-pattern in java, so if you whant be save with null you should you kind of not null check like if(x!=null) or assert.
Also I advice you read more about exceptions in java and differences between checked/unchecked exceptions and so on.
PS here is good topic about null checks.
Related
I made a switch case statement menu with one of the options being System.exit(0);. This is all surrounded by a try, finally that calls the method all of this is in. Would you guys not recommend this style of loop or am I all good?
public void Run() {
Scanner myObj = new Scanner(System.in);
int menuInput;
try {
System.out.println(" 1) call something\n"
+"2) quit");
menuInput = myObj.nextInt();
myObj.nextLine();
switch(menuInput) {
case 1:
something();
break;
case 2:
System.exit(0);
break;
}
}catch (Exeption e ){
System.out.println("Something went wrong.");
}finally{
Run();
}
}
No.
What you have here is an infinite recursion. Eventually you'd overflow the stack.
Use an actual loop instead:
while (true) {
try {
// ...
} catch (Exception e) {
// ...
}
}
And you almost never want to call System.exit. Just break the loop instead.
Is this legal code? Yes.
Is what you have there recommended? No.
If the method throws an exception it's likely recalling it will throw again. See the quote below.
Calling it again in a tight loop without attempting remedy, at least waiting a recovery and counting failures (3 strikes out?) will just end up in a tight loop of failure and stack overflow here.
So:
Can you identify errors that retrying may work and only retry on those?
You should almost certainly include some kind of 'back-off' wait before retry.
Always (always!) include a maximum retry number after which you accept failure.
In my experience the only kind of failure that may work on retry is 'service unavailable' meaning an intermittent outage.
It may not be relevant, but things like (say) invalid credentials aren't going to fix themselves and ideally you don't resubmit those. That's particularly because you end up locking the account and being in an even worse state and possibly causing issues for others using the valid credential...
The other scenario is (say) file not found and you're using the non-existence of a file as a way of polling for something.
That's a poor design pattern and is a misuse of exception handling.
You should strongly prefer to use some kind for existence check in those cases and not let routine activity get confused with exception handling of issues.
Also if you do retry log each attempt (it may be useful later to see whether things are running smoothly or getting delayed in retry scenarios even if the go through eventually). But always differentiate a 'Warning' when retrying and 'Error' when 'throwing in the towel' and failing.
public class Runner {
private static int MAX_RETRIES=3;
private static int BACK_OFF_MILLIS=30000;
public void Run() throws Exception,InterruptedException {
final int TRIES=3;//In reality may be configured.
int trycount=1;
for(;;){
try{
tryRun();
return;
}catch(Exception e){
String message=e.getMessage();
if(trycount>=MAX_RETRIES){
System.out.println("*FAILED*: "+e.getMessage());
throw e;
}
boolean retriable=true;
//Any tests for non-retriable exceptions here...
if(!retriable){
System.out.println("*FAILED*: non-retriable exception - "+e.getMessage());
throw e;
}
++trycount;
System.out.println("Warning: "+e.getMessage()+" retrying "+ trycount+" of "+TRIES);
try {
Thread.sleep(trycount*BACK_OFF_MILLIS);//Some kind of back-off...
}catch(InterruptedException ie){
System.out.println("*FAILED*: Interrupted. Aborting.");
throw ie;
}
continue;
}
}
}
public void tryRun() throws Exception{
//Real workload goes here!
}
}
NB: The back-off strategy here is very simplistic. When it comes to outages then it's usually recommended to implement a random element and an increasing back-off like 1 minute, 10 minutes, 25 minutes. But that's a topic in itself.
I'm not sure who really said but this popular quote seems relevant.
The definition of insanity is doing the same thing over and over again
and expecting different results
I'm just starting to get familiar with the CompletableFuture tool from Java. I've created a little toy application to model some recurrent use case almost any dev would face.
In this example I simply want to save a thing in a DB, but before doing so I want to check if the thing was already saved.
If the thing is already in the DB the flow (the chain of completable futures) should stop and not save the thing. What I'm doing is throwing an exception so eventually I can handle it and give a good message to the client of the service so he can know what happened.
This is what I've tried so far:
First the code that try to save the thing or throw an error if the thing is already in the table:
repository
.query(thing.getId())
.thenCompose(
mayBeThing -> {
if (mayBeThing.isDefined()) throw new CompletionException(new ThingAlreadyExists());
else return repository.insert(new ThingDTO(thing.getId(), thing.getName()));
And this is the test I'm trying to run:
CompletableFuture<Integer> eventuallyMayBeThing =
service.save(thing).thenCompose(i -> service.save(thing));
try {
eventuallyMayBeThing.get();
} catch (CompletionException ce) {
System.out.println("Completion exception " + ce.getMessage());
try {
throw ce.getCause();
} catch (ThingAlreadyExist tae) {
assert (true);
} catch (Throwable t) {
throw new AssertionError(t);
}
}
This way of doing it I took it from this response: Throwing exception from CompletableFuture ( the first part of the most voted answer ).
However, this is not working. The ThingAlreadyExist is being thrown indeed but it's never being handled by my try catch block.
I mean, this:
catch (CompletionException ce) {
System.out.println("Completion exception " + ce.getMessage());
try {
throw ce.getCause();
} catch (ThingAlreadyExist tae) {
assert (true);
} catch (Throwable t) {
throw new AssertionError(t);
}
is never executed.
I have 2 questions,
Is there a better way?
If not, am I missing something? Why can't I handle the exception in my test?
Thanks!
Update(06-06-2019)
Thanks VGR you are right. This is the code working:
try {
eventuallyMayBeThing.get();
} catch (ExecutionException ce) {
assertThat(ce.getCause(), instanceOf(ThingAlreadyExists.class));
}
By unit testing your code wrapped up in a Future, you’re testing java’s Future framework. You shouldn’t test libraries - you either trust them or you don’t.
Instead, test that your code, in isolation, throws the right exceptions when it should. Break out the logic and test that.
You can also integration test your app to assert that your entire app behaves correctly (regardless of implementation).
You have to be aware of the differences between get() and join().
The method get() is inherited from the Future interface and will wrap exceptions in an ExecutionException.
The method join() is specific to CompletableFuture and will wrap exceptions in a CompletionException, which is an unchecked exception, which makes it more suitable for the functional interfaces which do not declare checked exceptions.
That being said, the linked answer addresses use cases where the function has to do either, return a value or throw an unchecked exception, whereas your use case involves compose, where the function will return a new CompletionStage. This allows an alternative solution like
.thenCompose(mayBeThing -> mayBeThing.isDefined()?
CompletableFuture.failedFuture(new ThingAlreadyExists()):
repository.insert(new ThingDTO(thing.getId(), thing.getName())))
CompletableFuture.failedFuture has been added in Java 9. If you still need Java 8 support, you may add it to your code base
public static <T> CompletableFuture<T> failedFuture(Throwable t) {
final CompletableFuture<T> cf = new CompletableFuture<>();
cf.completeExceptionally(t);
return cf;
}
which allows an easy migration to a newer Java version in the future.
I am trying to follow this tutorial JUnit 5: How to assert an exception is thrown?
I use Java 10, IntelliJ 2018 and Junit 5.
I make a calculator app that adds 2 fractions. It checks whether the input has 0 in the denominator.
When I run the test The exception Message get printed out "Undefined Math Expression" but my IDE says "Expected java.lang.Throwable to be thrown, but nothing was thrown." I think there is some problem with the scope of my code? I'm a newbie, please be kind. I provided the code and the test below:
public class Calculator {
public static int[] calculate (int firstNumerator, int firstDenominator, int secondNumerator, int secondDenominator) {
String exceptionMessage = "Undefined Math Expression";
int resultNumerator;
int resultDenominator;
int[] result = new int[2];
resultNumerator = (firstNumerator * secondDenominator) +
(secondNumerator * firstDenominator);
resultDenominator = firstDenominator * secondDenominator;
try {
if (resultDenominator == 0) {
throw (new Throwable(exceptionMessage));
} else {
result[0] = resultNumerator;
result[1] = resultDenominator;
}
} catch (Throwable e) {
System.out.println(e.getMessage());
}
return result;
}
}
The test:
class CalculatorTest {
#Test
void denominatorContainsZero() {
assertThrows(Throwable.class, () -> {
Calculator.calculate(0,0,0,0);
});
}
}
The misunderstanding here appears to be in what JUnit can actually see.
JUnit isn't magical: it's just plain old Java. It can't see inside your methods to see what they are doing. All it can see is what any other code can see when it executes a method: the return value and uncaught exceptions (as well as any side effects of the method, if they are visible to the calling code).
Your method here doesn't throw an exception from the perspective of a caller: internally, it throws the exception, but it catches and handles it.
If you want JUnit to test that an exception is thrown, you need to not catch that exception.
It is never (*) the right thing to do to throw an exception and then catch and handle it yourself. What's the point? You can simply do the thing you do to handle it, without throwing the exception. Exceptions are expensive to throw, because of the need to capture the entire stack trace.
Throwable is never (*) the right exception to throw. It's the exception "equivalent" of returning Object: it conveys no type information about the exception to the caller, who then either has to do a lot of work to try to handle it; or, more realistically, should just propagate it themselves. IllegalArgumentException is the right exception to throw here, if you actually needed to throw (and not catch) an exception.
Throwable is rarely the right thing to catch. Throwable is a supertype of both Exception and Error, so you might unintentionally catch an Error, like OutOfMemoryError, which shouldn't be caught because there is nothing reasonable to do except crash your program. Catch the most specific type you can; which also means that you should throw the most specific type you can (or, at least, a type appropriate to the abstraction).
(*) This is "never" as in "ok, there are a limited number of circumstances where it may be appropriate". But unless you understand what these are, don't.
The Throwable is catched by try catch block, so Junit can not access it. Try remove the try catch block.
You are not actually throwing exception, you are catching it. For this to work, you should remove try catch block.
In Java, what is the difference (in term of performance) between:
for (int i = 0; i < count; i++) {
try {
// code that throws Exception
} catch (Exception e) {
e.printStackTrace();
}
}
and
try {
for (int i = 0; i < count; i++) {
// code that throws Exception
}
} catch (Exception e) {
e.printStackTrace();
}
In your first version the loop continues if it hits an exception, in the second version the loop continues after the catch block. That is the most important difference of those code snippets.
You can use both, but it all depends on what you want it to do. If you want to continue the execution after the loop finishes once then you do it the first way. If you want to catch an exception then stop executing the loop then you do the second. Performance wise it all depends on what you want to do with it.
The main difference is that in the first snippet of code, even if there is an exception thrown from the try block and it is caught execution of the for loop continues. In the second snippet if an exception is thrown then the for loop is exited. This is because the whole loop is within the try block.
No I'm quite sure there's absolutely no difference from a point of performance here (ignoring the obvious fact about the loop). In both cases you create exactly one entry in the exception table - only the PC values (ie in which range the exception is valid) will be a bit different.
ie if you assume the following is the exception table the only thing that'll change are the x, y and z values..
Exception table:
from to target type
x y z <Class java.lang.Exception>
Since you asked about performance in the two versions of code, I am reminded of "Practical Java" (Addison-Wesley 2000) which recommends in Praxis 23: Place try/catch blocks outside of loops. The reason involves running the code on a JVM with the JIT compiler turned off. In that case, the lack of run-time JIT optimizations results in extra branches in the opcode, leading to reduced performance. You can read JIT docs of 2014 here: http://www.oracle.com/technetwork/articles/java/architect-evans-pt1-2266278.html
Besides the difference in your logic with the continuing for. It's no noticeable difference between
try {
lots of stuff which might not throw any exception
something that throws exception
} catch (Exception e) {
}
and
lots of stuff which might not throw any exception
try {
something that throws exception
} catch (Exception e) {
}
I recently came across code written by a fellow programmer in which he had a try-catch statement inside a catch!
Please forgive my inability to paste the actual code, but what he did was something similar to this:
try
{
//ABC Operation
}
catch (ArgumentException ae)
{
try
{
//XYZ Operation
}
catch (IndexOutOfRangeException ioe)
{
//Something
}
}
I personally feel that it is some of the poorest code I have ever seen!
On a scale of 1 to 10, how soon do you think I should go and give him a piece of my mind, or am I over-reacting?
EDIT:
What he is actually doing in the catch, he is performing some operations which can/should be done when the initial try fails. My problem is with having a clean code and maintainability. Delegating the exception from the first catch to a different function or the calling function would be OK, but adding more code which may or may not throw an exception into the first catch, is what I felt was not good. I try to avoid multiple stacked "if-loop" statements, I found this equally bad.
Why is that bad? It's no different conceptually than:
void TrySomething() {
try {
} catch (ArgumentException) {
HandleTrySomethingFailure();
}
}
void HandleTrySomethingFailure() {
try {
} catch (IndexOutOfRangeException) {
}
}
Before you go over there and give him a piece of your brain (try the parietal lobe, it's particularly offensive) , what exactly are you going to say to him? How will you answer the proverbial "why?"
What's even more ironic is that when the jitter inlines this code, it will look exactly like your example.
-Oisin
Here is a case :
try{
//Dangerous Operation
} catch (AnyException ae) {
try {
//Do rollback which can fail
} catch (RollbackFailedException rfe) {
//Log that
}
} finally {
try {
//close connection but it may fail too
} catch (IOException ioe) {
//Log that
}
}
It's about the same thing as #x0n said. You might need to handle exception while try to close resources or while you're trying to resolve a situation brought by another exception.
Without knowing what the code does it's impossible to say. But it's not unusual to do this.
e.g. if you have to clear up resources whilst handling exceptions, that clear-up code itself may have the capability to throw exceptions.