Страницы

Поиск по вопросам

среда, 18 декабря 2019 г.

try/catch вместо if null

#java #if #try_catch


Часто бувает несколько и больше аргументов в условии которые необходимо проверить
на null. Мне надоело перечислять if(a!=null && b!=null || c!=null) и т.д. Я стал просто
обрамлять в try/catch и если что-то не так то просто вывожу сообщение, что одно из
условий отсутствует. Понятно что в некоторых случаях необходимо знать, что я получаю
и приходится использовать if.

Но все же является такая практика с t/c нормальной?
    


Ответы

Ответ 1



Примените что-то подобное: private boolean isNull(Object... objects) { if (objects != null) { for (Object object : objects) { if(object==null) return true; } } return false; } //использование if(isNull(a, b, c)) //blah-blah

Ответ 2



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

Ответ 3



Конструкция try/catch обходится дороже. Приведу тест замера времени для 1000000000 вызовов методов проверяющих аргумент на null явно и в попытке и выведу результат замера в консоль: public class Test { public static void main(String[] args) { long start, end; start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) method(null); end = System.currentTimeMillis(); System.out.println("Check null: " + (end-start)); start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) methodWithTry(null); end = System.currentTimeMillis(); System.out.println("Try/catch: " + (end-start)); } public static int method(String s) { if (s != null) { return s.length(); } return 0; } public static int methodWithTry(String s) { try { return s.length(); } catch (NullPointerException e) { return 0; } } } Результат: Check null: 15 Try/catch: 1404 UPD: Комментарий Artem Konovalov подтвердился. Судя по всему мой код был автоматически оптимизирован из-за того, что не был использован результат методов. Скорректированный код дает иные результаты: public class Test { public static void main(String[] args) { int c = 0; long start, end; start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) if (i%2==0) { c += method(null); } else { c += method(i); } end = System.currentTimeMillis(); System.out.println("Check null: " + (end-start)); start = System.currentTimeMillis(); for (int i = 0; i < 1000000000; i++) if (i%2==0) { c += methodWithTry(null); } else { c += methodWithTry(i); } end = System.currentTimeMillis(); System.out.println("Try/catch: " + (end-start)); } public static int method(Integer i) { if (i != null) { return i.intValue(); } return 0; } public static int methodWithTry(Integer i) { try { return i.intValue(); } catch (NullPointerException e) { return 0; } } Результат: Check null: 1702 Try/catch: 3654

Ответ 4



Однозначно, сказать нельзя, какой вариант лучше. В этой ситуации стоит учитывать несколько моментов. Исключения, как правило, используются для необычных ситуаций, когда выполнение программы пошло не так, как задумывал программист - получены некорректные параметры, внешние ошибки и пр. Из этого можно вывести, что: Если вы пишите код, который будет доступен для вызова сторонними разработчиками, то выкидывание NullPointerException вполне оправдано. Если этот код, является частью внутреннего компонента, то использование блока try-catch-finally, не вполне оправдано. Получение null, говорит о том, что код некорректен, т.е. такая ситуация ненормальна. В идеале, в процессе отладки null проверяется assert'ами и все подобные ситуации вылавливаются в программе. Еще один довод против исключений, это более худная производительность. В моем тесте, разница была порядка 2x.

Комментариев нет:

Отправить комментарий