Можно ли использовать исключения для проверки границ массива?

Я хочу проверить, имеют ли данные координаты массив или нет.

public boolean checkBounds(int x, int y) {
    try {
        Object val = array[x][y];
        return true;
    } catch (ArrayIndexOutOfBoundsException e) {
        return false;
    }
}

Могу ли я сделать это так? Это эффективный способ сделать это?

Ответ 1

Что происходит, когда мы используем исключения для выполнения пограничных проверок?

Использование исключений для обработки операций, таких как проверка нуля, проверка границ, проверка наличия файлов, вводят много накладных расходов всякий раз, когда возникает исключение.

Что бы вы сделали, если бы вы просто проверили границы:

  • проверьте размер массива на 0 и на
  • результат возврата

Что вы на самом деле делаете при использовании проверки на основе исключений:

  • проверить границы массива
  • инициировать механизм исключения Java (со всеми его служебными данными)
  • создать новый объект Exception
  • удалить всю трассировку стека
  • заполнить вновь созданный объект всеми данными стека
  • catch исключение
  • вернуть результат

Сравнение производительности

С помощью этой простой тестовой программы я измерил скорость обоих типов проверок границ массива.

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, режим eclipse Run as:

time check=[911620628]
       exc=[1192569638]
diff=[280949010] percent diff=[30.818632375220886]

JDK 7, режим eclipse Debug:

time check=[931243924]
       exc=[651480777121]
diff=[650549533197] percent diff=[69858.12378809143]

Потеря скорости с отключенной отладкой не очень значительна, хотя она видна: код без исключений примерно на 30% быстрее (примерно для 50% ложных возвратов). Потери скорости в режиме отладки поразительны. Код на основе исключений работает примерно в 700 раз медленнее, чем обычная проверка размера массива прямо.

Философия исключений

Общая идея исключений заключается в том, чтобы разрешить обработку исключительных условий. В этом случае нет исключительного условия - проверка диапазона - это просто нормальная часть кода. По этой причине исключение не должно использоваться в этой ситуации.