Home > Enterprise >  Continue the execution after catching the error in try-catch block
Continue the execution after catching the error in try-catch block

Time:11-27

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.

  1. 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:

  1. I've used a specific exception type LinkedListInsertionException. Never catch and ignore Exception, as you'll end up missing all sort of other problems, e.g. NullPointerExceptions.
  2. Stick to Java naming conventions in your code. i.e. insert not Insert.
  3. Don't reuse JDK class names, i.e. use MyLinkedList not LinkedList.

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

  • Related