Preventing vs Ignoring Errors with a Try-Catch in Java - java

I have been working on a few projects lately that use a flood fill on a 2D array to create a grid map for a game.
Part of the flood fill algorithm I am using grabs the neighboring "cells" in the grid and floods them if they are an open space and ignores them if they are not.
However, because I am grabbing neighbor cells, I am grabbing items from the array relative to the current cell like this: grid[y][x-1].
Obviously, when x == 0 an out of bounds error is thrown. In order to address this I have been using a conditional statement to check that the index I am accessing is in the array. Like this:
if(x - 1 >= 0){do what I need to that neighbor}
I know I can also address the error by using a try catch.
However, I am not sure which is the proper solution.
There are a few specific questions I have:
1) Does using the conditional method to prevent an error from occurring, require more overhead and create less efficiency? (I may be flooding thousands of cells)
2) How exactly does the catch block work? Is it conditionally checking for errors in the background some how?
I also made a very small demo code to show you exactly what I am talking about, just scaled down:
public static void main(String[] args) {
//declare our test array and initialize size 3
String [] testArray = new String[3];
//This is here for one of the methods I have been trying to avoid errors on
int indexAdjuster = 5;
//this the index of the array we are adjusting
int i = 0;
//now throw an error! uncomment to confirm there is an error if you want
//testArray[i-indexAdjuster] = "error";
//testArray[i+indexAdjuster] = "error";
//IGNORE the error with a try catch
try{
//this would result in an out of bounds exception below index 0 (-5 specifically)
testArray[0-indexAdjuster] = "error";
//this would result in an out of bounds exception above index 2 (5 specifically)
testArray[0+indexAdjuster] = "error";
}catch(ArrayIndexOutOfBoundsException e){
System.out.println("There was an error, but I ignored it");
}
//PREVENT an error with a condition test
//it first checks if the adjusted index is at least 0
//then it checks if the adjusted index is less than the length of the array
if(i - indexAdjuster >= 0 && i + indexAdjuster < testArray.length){
//this would result in an out of bounds exception below index 0 (-5 specifically)
testArray[0 - indexAdjuster] = "This would be an error, but it is prevented";
//this would result in an out of bounds exception above index 2 (5 specifically)
testArray[0 + indexAdjuster] = "This would be an error, but it is prevented";
}else{
System.out.println("We just prevented the error");
}
System.out.println("Test Complete");
}

It depends, specifically on what you primary focus is: Speed or clean code.
If the error condition occurs rarely and the check is costly, catching an exception may be cheaper than checking beforehand. This conflicts the commonly accepted rule that catch blocks should not be used for regular flow control. Exceptions should be used to catch unexpected error conditions, an index outside an array is hardly unexpected.
The test can also be extracted into a separate method, making the code easier to read:
static boolean isValidIndex(String[] array, int i) {
return i >= 0 && i < array.length;
}
Or use a resilient access method:
static String getIndex(String[] array, int i) {
return i >= 0 && i < array.length ? array[i] : null;
}
(You may want to replace null with a constant value indicating an invalid value).
In your code you can simply use the getIndex() method for whatever index you calculated and act on the value it returns instead of the index. Same can be done for assigning to an index, if its appropiate to just ignore attempted assignments to non-existing indices:
static void setIndex(String[] array, int i, String value) {
if (i >= 0 && i < array.length)
array[i] = value;
}
The main issue you face is deciding if an out-of-bounds condition is just a normal case that has a reasonable default handling option or if it represents a real error that warrants aborting the method or program.
If its a real error condition, don't prevent it, don't catch it. Let it throw and bubble up the call stack. Whatever caller level initiated the whole action should be the one that responds to the execption. Its important to decide sensibly who is responsible for the handling, a deep-down detail method has often not enough information to make a reasonable decision what an error means - in those cases assign the responsibility to the caller (repeat until the caller can make the decision).

Using if statement to check your boundaries cause lots of overhead in each loop iteration.
I suggest you allocate a bigger array by 1 like:
String [] testArray = new String[3+1];
This cause that you don't need any if condition.
In response to your question about exception handling, it does not run any condition in background. It runs your code and after causing access violation determines you catch clauses.

Related

Error array index out of bounds in some code

There is an array index out of bounds exception in my recursive function. Can someone try to point out to me why that is the case?
This line: return minChange(a, IntegerList); is having the array index out of bounds exception as well as most likely this line:
return minimumValue(1 + minChange(a - d, integerList), minChange(a, updatedList));
/* Function minChange: Minimum Change
Pseudo-code:
minChange(0, ds) = 0
minChange(a, []) = Failure
minChange(a, d :: ds) = minChange(a,ds) if d > a
minChange(a, d :: ds) = min(1 ++ minChange(a - d, d :: ds) otherwise
*/
public int minChange(int a, List<Integer> integerList) {
//int minimumResult = 0;
int indexNumber = 0;
int d = integerList.get(indexNumber); (line 246)
if(a == 0) {
// If a is 0 return 0
return 0;
} else if(integerList.isEmpty()) {
return -1;
} else if(d > a) {
integerList.remove(indexNumber); // Remove first element from list
// Recursive call to minChange
return minChange(a, integerList); (line 261)
} else {
// Create updatedList and remove first element
List<Integer> updatedList = integerList;
updatedList.remove(indexNumber);
indexNumber++;
return minimumValue(1 + minChange(a - d, integerList), minChange(a, updatedList)); (line 269)
}
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 0 out-of-bounds for length 0
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:246)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:261)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
at AlgorithmsSetZero.minChange(AlgorithmsSetZero.java:269)
How can I fix this array index out of bounds exception. It seems one line needs to be fixed. If so how can I fix this error? What are some ways?
Why it Fails:
A specific sequence of events that leads to the out of bounds exception would be, for example:
minChange(1, [4]) // goes into second-to-last (else if) case, since 4 > 1. 4 is then removed.
minChange(1, []) // crashes
It's not clear what your code was intended to do in this case, since your pseudo-code doesn't define minChange(a, ds).
Even if we stipulate that the input list has to have more than one item, we'll often hit this same case:
minChange(5,[4, 8])
minChange(1,[8])
minChange(1,[])
I'm not sure what you intended to happen here, but, anyway, there are other issues...
Bugs:
There is very likely a bug in your code with this line:
// this just creates another reference to the existing list
// https://stackoverflow.com/questions/6536094/java-arraylist-copy
// meaning: both recursive calls will operate on the same list
// even though one uses the "updatedList" reference and one uses "integerList"
List<Integer> updatedList = integerList;
Also, the use of indexNumber indicates a bug, since it's only ever used when it has value 0 - the incrementing is pointless. Remember that local variables in the function are getting 'reset' in each recursive call, unless you pass them as a parameter.
Debugging Strategies:
First, clarify what you actually want the algorithm to do.
Then, check what it's actually doing. As a debugging technique, I would recommend adding some print statement at the start of the function call:
System.out.println("minChange(" + a + ", " + integerList + ")");
...so that you can see a log of what happened before the crash. You can also use a debugger for this purpose.
Finally, once it works on some simple cases, write a fuzz tester that checks your algorithm on a bunch of random lists and as of different sizes, to see if there are any cases that you missed.

How to get the number of rows that contain a certain word?

So i have this code-generated table and i've been trying to get this code to work, basically i want to know how many rows have the word so i can later work with that number of elements, this code is like not working maybe you guys can see the error?
Code:
public int UntilArraySearch (String filtro){
int tope=0;
for(int i = 0;i<mTableLayout.getChildCount();i++){
if(data[i].productName.contains(filtro) || data[i].productCode.contains(filtro))
tope++;
}
return tope;
}
And this error pops up:
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=52; index=52
I get this error whenever i run the function
Your loop would work only if mTableLayout.getChildCount() is <= data.length and it seems that it is not, because if it was the case then i would not exceed the max index for data.
Since you want to iterate through data, why don't you write the loop like this:
for(int i = 0;i<data.length;i++){
if(data[i].productName.contains(filtro) || data[i].productCode.contains(filtro))
tope++;
}
and check if this is the expected result?
If you are searching through data, then you might as well iterate over the length of the data array. Whether or not your view (mTableLayout) properly reflects the model (data), this operation can better isolate itself from the view by only considering the model which is a good practice to follow in general.
public int UntilArraySearch (String filtro){
int tope=0;
for(int i = 0;i<data.length;i++){
if(data[i].productName.contains(filtro) || data[i].productCode.contains(filtro))
tope++;
}
return tope;
}

Java - Index Out Of Bounds Exception: Index: 1, Size: 2

While working on some java project I encountered this peculiar error:
java.lang.IndexOutOfBoundsException: Index: 1, Size: 2
How can there be an index out of bounds exception? Index 1 means it tries to get the second element, Size 2 means there are 2 elements, so there shouldn't be a problem, no?
Context:
I have the following function:
public int howManyAgents(){
// cell is a class that can have 0 or multiple objects
// I get a list of cells that contain at least 1 agent
List<Cell> cellsWithAgents = getNonEmptyCells();
// initializing a counter
int agentsCount = 0;
for(int i=0; i<cellsWithAgents.size(); i++){
// For every cell in the list I add to the counter the number of
// agents that cell contains
agentsCount += cellsWithAgents.get(i).howManyAgents();
}
return agentsCount;
}
Now, the problem was that I got a null pointer exception at the line:
agentsCount += cellsWithAgents.get(i).howManyAgents();
I want to debug the code, but this function is called many times while the program is running and the null pointer exceptions comes up at different points in time (after 10 seconds after 1 minute after 5 minutes). So I tried to come up with a method to have e breakpoint when the cell is null so I came up with this code:
public int howManyAgents(){
// cell is a class that can have 0 or multiple objects
// I get a list of cells that contain at least 1 agent
List<Cell> cellsWithAgents = getNonEmptyCells();
// initializing a counter
int agentsCount = 0;
for(int i=0; i<cellsWithAgents.size(); i++){
int pass;
if (null == cellsWithAgents.get(i))
pass = 1; // breakpoint here
// For every cell in the list I add to the counter the number of
// agents that cell contains
agentsCount += cellsWithAgents.get(i).howManyAgents();
}
return agentsCount;
}
Of course, it is not the best method. The most logical way is jut to surround the code with try/catch and put the breakpoint there. The point is that the code above didn't work. It did not stop at the breakpoint but instead it threw the index out of bounds exceptions at the line:
if (null == cellsWithAgents.get(i))
Why? How can it be possible to throw an index out of bound exception if apparently the index is in bounds?
Edit: changed a mistake in copying the code
Update:
I have tried to see why the null pointer exception appears with a try/catch and put a breakpoint there. It seems that cellsWithAgents sometimes contains a null. This is, most probably because of concurrency as #rlinden stated.
About concurrency: there are some cells that can contain agents. There is a variable number of agents that can move between the cells. There is a special agent that tries to count how many moving agents there are (using this function).
So, only one agent (thread) can use this function, but multiple agents can modify cells (and thus mess with getNonEmptyCells() and howManyAgents() results).
Still, how it is possible to get index out of bounds with size 2 and index 1? It is not possible because of the concurrency, is it? Because only this thread can change the list cellsWithAgents. So, even if one of the elements in the list becomes null, the list still contains that number of pointers, so the size of the list cannot change. Or can it in some way that I miss?
And how can it be explained that the stack trace prints Index:1 Size: 2?
New Idea
Try changing the loop and see if the error persists:
int agentsCount = 0;
for(Cell cell : getNonEmptyCells()) {
if(cell != null) {
agentsCount += cell.howManyAgents();
} else {
System.out.println("Found a null cell");
}
}
I would like to see the code of the method getNonEmptyCells(). If your program is actually multithreaded and this function returns a fixed List that is changed at every interaction, then it is possible that changes in following executions have affected the previous, unfinished ones.
This is due to the fact that the line cellsWithAgents = getNonEmptyCells(); does not create a copy, but a reference to the return value of getNonEmptyCells(). So, if this method reuses the return object, it is possible that the first execution would believe there was two, but the concomitant thread changed the content size to less than 2.
The problem is, program is throwing exception at cellsWithType.get(i). What you can do is either put a breakpoint at if (null == cellsWithType.get(i)) and try debug it. Or change it to,
if (i >= cellsWithType.size())
pass = 1; // breakpoint here

NextInt giving Force close

Whenever I try to execute this it gives me FC on my application
int a, b;
Random s = new Random();
if (diffi.contains("easy") && name.contains("sub")) {
a = s.nextInt(21);
b = s.nextInt(a);
}
But when remove "a " and put a number in its place then it starts working
int a, b;
Random s = new Random();
if (diffi.contains("easy") && name.contains("sub")) {
a = s.nextInt(21);
b = s.nextInt(21);
}
I want the second number "b" to be smaller than a in all cases
You'll get an exception if the first call to nextInt returns 0. Then the second call can't return a value which is greater than or equal to 0 but less than 0, hence the exception.
From the docs for Random.nextInt:
Throws: IllegalArgumentException - if n is not positive
You should step back for a moment though, and work out why your diagnostic approach didn't actually see those exception details. Did you check the application logs? I'd expect the exception to be clear, with the right exception, which would then make it fairly obvious what was wrong.
EDIT: I very much doubt that it's actually throwing an exception whenever that code is executed. Instead, I suspect that either that code is executing many times (so eventually you'll see that a is 0 and the exception will be thrown) or you've just been unlucky.

Index out of bounds exception in homework

I'm trying to do a homework assignment. I have to use dynamic programming to display whether the next person to move is in a win/loss state. I don't need help with the actual problem, I need help with an index out of bounds exception I'm getting that baffles me. I'm only going to paste part of my code here, because I only need the for loops looked at. I also don't want anyone in my class seeing all my code and copying it. If you need more data please let me know. So here is the code:
if(primeArray[x] == true){
for(int i = 1; i <= x; i++){
if(primeArray[i]== true){
newRowNumber = x - i;
}
if(dynaProgram[newRowNumber][columnNumber] < minimum){
minimum = dynaProgram[newRowNumber][columnNumber];
}
}
}
//COMPOSITE CASE FOR X!
else{
for(int k = 1; k <= x; k++){
if((primeArray[k] == false)){
newRowNumber = x - k;
}
if(dynaProgram[newRowNumber][columnNumber] < minimum){
minimum = dynaProgram[newRowNumber][columnNumber];
}
}
For some reason the if(primeArray[i] == true runs correctly, but I'm getting index out of bounds exception on if(primeArray[k] == false. The only difference between these two is the use of the variable k over i in the for loop.(the for loops are identical) I haven't used either variables anywhere else in my code. I have no idea why this occurs for one but not the other. In both cases, x remains the same number.
I am also getting an index out of bounds exception on the second minimum = dynaProgram[newRowNumber][columnNumber], while the first doesn't encounter an error. I know it's probably a stupid error, but I can't figure it out. If I change the 'k' for loop to k < x the index of out bounds exception in the if(primeArray[k] == false line goes away, but then it isn't correct. (The error on the second minimum = dynaProgram[newRowNumber][columnNumber] doesn't go away however.)
All this code is in a nested for loop which iterates through the rows and columns in the table to fill them in. If I remove the above code and just put dynaProgram[rowNumber][columnNumber] = 1 I don't have an issue, so I don't believe that is the problem.
When accessing an array of length 5 (for example)
int[] fred = new int[5];
the first element will be fred[0] and the last will be fred[4]
So when doing something like:
if(primeArray[i]== true){
Make sure that i is less than the array length. Using a value of i equal to the array length will throw an exception.

Categories