Issue
I have a loop that looks something like this:
for (int i = 0; i < max; i++) {
String myString = ...;
float myNum = Float.parseFloat(myString);
myFloats[i] = myNum;
}
This is the main content of a method whose sole purpose is to return the array of floats. I want this method to return null
if there is an error, so I put the loop inside a try...catch
block, like this:
try {
for (int i = 0; i < max; i++) {
String myString = ...;
float myNum = Float.parseFloat(myString);
myFloats[i] = myNum;
}
} catch (NumberFormatException ex) {
return null;
}
But then I also thought of putting the try...catch
block inside the loop, like this:
for (int i = 0; i < max; i++) {
String myString = ...;
try {
float myNum = Float.parseFloat(myString);
} catch (NumberFormatException ex) {
return null;
}
myFloats[i] = myNum;
}
Is there any reason, performance or otherwise, to prefer one over the other?
Edit: The consensus seems to be that it is cleaner to put the loop inside the try/catch, possibly inside its own method. However, there is still debate on which is faster. Can someone test this and come back with a unified answer?
Solution
All right, after Jeffrey L Whitledge said that there was no performance difference (as of 1997), I went and tested it. I ran this small benchmark:
public class Main {
private static final int NUM_TESTS = 100;
private static int ITERATIONS = 1000000;
// time counters
private static long inTime = 0L;
private static long aroundTime = 0L;
public static void main(String[] args) {
for (int i = 0; i < NUM_TESTS; i++) {
test();
ITERATIONS += 1; // so the tests don't always return the same number
}
System.out.println("Inside loop: " + (inTime/1000000.0) + " ms.");
System.out.println("Around loop: " + (aroundTime/1000000.0) + " ms.");
}
public static void test() {
aroundTime += testAround();
inTime += testIn();
}
public static long testIn() {
long start = System.nanoTime();
Integer i = tryInLoop();
long ret = System.nanoTime() - start;
System.out.println(i); // don't optimize it away
return ret;
}
public static long testAround() {
long start = System.nanoTime();
Integer i = tryAroundLoop();
long ret = System.nanoTime() - start;
System.out.println(i); // don't optimize it away
return ret;
}
public static Integer tryInLoop() {
int count = 0;
for (int i = 0; i < ITERATIONS; i++) {
try {
count = Integer.parseInt(Integer.toString(count)) + 1;
} catch (NumberFormatException ex) {
return null;
}
}
return count;
}
public static Integer tryAroundLoop() {
int count = 0;
try {
for (int i = 0; i < ITERATIONS; i++) {
count = Integer.parseInt(Integer.toString(count)) + 1;
}
return count;
} catch (NumberFormatException ex) {
return null;
}
}
}
I checked the resulting bytecode using javap to make sure that nothing got inlined.
The results showed that, assuming insignificant JIT optimizations, Jeffrey is correct; there is absolutely no performance difference on Java 6, Sun client VM (I did not have access to other versions). The total time difference is on the order of a few milliseconds over the entire test.
Therefore, the only consideration is what looks cleanest. I find that the second way is ugly, so I will stick to either the first way or Ray Hayes’s way.
Answered By – Michael Myers
Answer Checked By – Marilyn (BugsFixing Volunteer)