Можно ли использовать исключения для проверки границ массива?
Я хочу проверить, являются ли данные координаты массивом или нет.
public boolean checkBounds(int x, int y) {
try {
Object val = array[x][y];
return true;
} catch (ArrayIndexOutOfBoundsException e) {
return false;
}
}
Могу ли я сделать это так? Это эффективный способ сделать это?
1 ответ
Что происходит, когда мы используем исключения для проверки границ?
Использование исключений для обработки таких операций, как проверка нуля, проверка границ, проверка существования файла, приводит к большим накладным расходам при каждом возникновении исключения.
Что бы вы сделали, если бы просто проверили границы:
- проверить размер массива от 0 до
- вернуть результат
Что вы на самом деле делаете при использовании проверки на основе исключений:
- проверить границы массива
- инициировать механизм исключений Java (со всеми его издержками)
- создать новый объект Exception
- выгрузить всю трассировку стека
- заполнить вновь созданный объект всеми данными стека
- поймать исключение
- вернуть результат
Сравнение производительности
С помощью этой простой тестовой программы я измерил скорость обоих типов проверки границ массива.
public class BoundsCheckTest {
final static int[] array = new int[1];
final static Random gen = new Random();
public static void main(String[] args){
boolean ret = false;
int tries = 100000000;
long timestart = System.nanoTime();
for (int a=0; a< tries; a++) {
ret = method1();
}
long timeend1 = System.nanoTime();
System.out.println();
for (int a=0; a< tries; a++) {
ret = metod2();
}
long timeend2 = System.nanoTime();
System.out.println();
long t1 = timeend1-timestart;
long t2 = timeend2-timeend1;
System.out.println("\ntime 1=["+t1+"]\n 2=["+t2+"]"+
"\ndiff=["+Math.abs(t1-t2)+"] percent diff=["+(100d*t2/t1-100)+"]");
}
private static boolean metod2() {
try {
int val = array[gen.nextInt(2)];
return true;
} catch (Exception e) {
return false;
}
}
private static boolean method1() {
return array.length < gen.nextInt(2);
}
}
Результаты, достижения:
JDK 7, затмение Run as
Режим:
time check=[911620628]
exc=[1192569638]
diff=[280949010] percent diff=[30.818632375220886]
JDK 7, затмение Debug
Режим:
time check=[931243924]
exc=[651480777121]
diff=[650549533197] percent diff=[69858.12378809143]
Потеря скорости при отключенной отладке не очень значительна, хотя и заметна: код без исключений работает примерно на 30% быстрее (примерно для 50% ложных возвратов). Потеря скорости в режиме отладки удивительна. Код, основанный на исключениях, выполняется примерно в 700 раз медленнее, чем обычная проверка размера прямого массива.
Философия исключений
Общая идея, лежащая в основе исключений, состоит в том, чтобы предоставить способ обработки условий исключений. В этом случае нет никаких исключительных условий - проверка диапазона - это просто нормальная часть кода. Только по этой причине исключение не должно использоваться в этой ситуации.