After catching an exception, how do I continue the execution of a Java program?
So I made a program to insert or delete nodes from specific positions in Doubly Linked List. Those 2 methods throw exception.
In main method, I have started to insert some int values to positions. If I entered wrong pos value insert method throws an error and catch block handle.
- If I have entered 30 nodes and insert them to the correct positions except 1 Node. -After false entry (i.e in the middle of the insertions) how can I continue to insert the rest?
public static void main(String[] args) {
LinkedList myList = new LinkedList();
try {
myList.Insert(1, 0);
myList.Insert(5, 54); // this is the false entry
myList.Insert(1, 0);
myList.Insert(1, 0);
} catch (Exception ex) {
System.out.println(ex.toString());
}
myList.Out();
myList.ReverseOutput();
}
}
So after execution, the output is 1. How can I make it [1 , 1 , 1]?
CodePudding user response:
You can wrap myList.insert
in a method which ignores the Exception, and use that instead:
static void insertAndIgnoreException(LinkedList list, int position, int value) {
try {
list.Insert(position, value);
} catch (LinkedListInsertionException e) {
System.out.println(e.getMessage());
}
}
So your main becomes:
public static void main(String[] args) {
LinkedList myList = new LinkedList();
insertAndIgnoreException(1, 0);
insertAndIgnoreException(5, 54); // this is the false entry
insertAndIgnoreException(1, 0);
insertAndIgnoreException(1, 0);
myList.Out();
myList.ReverseOutput();
}
Some notes:
- I've used a specific exception type
LinkedListInsertionException
. Never catch and ignoreException
, as you'll end up missing all sort of other problems, e.g.NullPointerException
s. - Stick to Java naming conventions in your code. i.e.
insert
notInsert
. - Don't reuse JDK class names, i.e. use
MyLinkedList
notLinkedList
.
CodePudding user response:
In this example, you can solve this by using a loop.
Something like:
int[] numsToInsert = new int[] {1, 0, 5, 54, 1, 0, 1, 0};
for(int i = 0; i < 8; i = 2){
try {
myList.Insert(numsToInsert[i], numsToInsert[i 1]);
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
This will catch the exception separately for each insertion by performing the insertions iteratively.
CodePudding user response:
The short answer is: you don't.
... but that doesn't mean there is nothing you can do.
The purpose to a try/catch is stop all processing once an error is detected. It's purpose is to skip the rest of the code (through to the catch). It's doing exactly what it is supposed to do, it is the same as saying "skip me".
So your question "how do I run the rest of the code" can only be acheived by removing the code from "skip me" instruction.
try {
myList.Insert(1, 0);
myList.Insert(5, 54); // this is the false entry
} catch (Exception ex) {
System.out.println(ex.toString());
}
myList.Insert(1, 0);
myList.Insert(1, 0);
myList.Out();
myList.ReverseOutput();
This will give you the output you expect.
... but it doesn't feel quite right
If we are removing code from the try
it almost seems like the try isn't worth having. The thing is, that try block was put there there for some reason. Try blocks are supposed to catch errors and it successfully did so, so obviously its doing something useful, and taking the code out of it feels like the wrong solution.
What we want is for each one of the lines of code to be tried, and if it fails, try the next one. Notice I said try
more than once, and also "each one"
try {
myList.Insert(1, 0);
} catch (Exception ex) {
System.out.println(ex.toString());
}
try {
myList.Insert(5, 54); // this is the false entry
} catch (Exception ex) {
System.out.println(ex.toString());
}
try {
myList.Insert(1, 0);
} catch (Exception ex) {
System.out.println(ex.toString());
}
try {
myList.Insert(1, 0);
} catch (Exception ex) {
System.out.println(ex.toString());
}
This will also give you the output you want, and also handles any of those inserts kicking out an error.
... but it doesn't feel quite right
That's a lot of repetitive text, just to do the same insert over and over. If only we had a way to repeat things?
int values[4][2] = {
{1,0},
{5,54},
{1,0},
{1,0}
};
for(int v[2] : values){
try {
myList.Insert(v[0], v[1]);
} catch (Exception ex) {
System.out.println(ex.toString());
}
}
This will give you the output you want, handles any of the inserts kicking out an error, and avoids the constant repetition.
... but it doesn't feel quite right
There was no loop being used for that original code. I assume that was for a reason: possibly it was a test stub that will eventually be receiving values from somewhere else.
This indicates that having each item tested independantly is the actual purpose of this code. If so, there is a way that we could have the single line of code handle its own error:
function TryInsert(list,pos,val){
try {
list.Insert(pos, val);
return true;
} catch (Exception ex) {
System.out.println(ex.toString());
return false;
}
}
...
TryInsert(mylist, 1, 0);
TryInsert(mylist, 5, 54); // this is the false entry
TryInsert(mylist, 1, 0);
TryInsert(mylist, 1, 0);
This will give you the output you want, handles any of the inserts kicking out an error, and is more true to the original intent.
... but it doesn't feel quite right
Given you are passing in the myList
object to every function call, it seems like that object is the thing to be acted upon. This would indicate that this is the true desired behaviour of your Insert
function.
Perhaps you would like to alter your class, either to add this function to it, or modify the Insert
to act on its own best judgement when the error occurs (either directly or through inheritance).
myList.TryInsert(1, 0);
myList.TryInsert(5, 54); // this is the false entry
myList.TryInsert(1, 0);
myList.TryInsert(1, 0);
Given I don't have access to your class ... I leave it as an exercise to the reader.
refactoring is fun