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

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

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 раз медленнее, чем обычная проверка размера прямого массива.

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

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

Другие вопросы по тегам