LBYL по сравнению с EAFP в Java?

Неустранимая ошибка: вызов функции-члена ... на не-объект

происходит с кодом, подобным xyz->method(), где xyz не является объектом и, следовательно, method не может

Это фатальная ошибка, которая остановит сценарий (уведомление о прямой совместимости: это станет захватывающей ошибкой, начиная с PHP 7).

Чаще всего это знак что в коде отсутствуют проверки условий ошибок. Убедитесь, что объект фактически является объектом перед вызовом его методов.

Пример типичного будет

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

В приведенном выше примере запрос не может и prepare() назначит false на $statement. Попытка вызвать метод execute() приведет к Fatal Error, потому что false является «не объектом», потому что значение является логическим.

Выясните , почему ваша функция вернула логическое значение вместо объекта. Например, проверьте объект $pdo для последней произошедшей ошибки. Подробности о том, как отлаживать это, будут зависеть от того, как обрабатываются ошибки для конкретной рассматриваемой функции / объекта / класса.

Если даже сбой ->prepare не выполняется, то ваш дескриптор

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

базы данных

// ... some code using PDO
$statement = $pdo->prepare('invalid query', ...);
$statement->execute(...);

не попал в текущий объем . Найдите, где он определился. Затем передайте его как параметр, сохраните его как свойство или поделите его через глобальную область.

Другой проблемой может быть условное создание объекта, а затем попытка вызова метода вне этого условного блока. Например,

if ($someCondition) {
    $myObj = new MyObj();
}
// ...
$myObj->someMethod();

Пытаясь выполнить метод вне условного блока, ваш объект не может быть определен.

Вопросы, относящиеся:

59
задан Eric 12 July 2015 в 18:23
поделиться

4 ответа

Лично, и я думаю, что это сохранено условно, EAFP никогда не является хорошим способом пойти. Можно посмотреть на него как на эквивалент следующему:

if (o != null)
    o.doSomething();
else
    // handle

в противоположность:

try {
    o.doSomething()
}
catch (NullPointerException npe) { 
    // handle
}

, Кроме того, рассмотрите следующее:

if (a != null)
    if (b != null)
        if (c != null)
            a.getB().getC().doSomething();
        else
            // handle c null
    else
        // handle b null
else
    // handle a null

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

способ, которым я вижу его EAFP, никогда не должен использоваться, за исключением редких ситуаций. Кроме того, так как Вы подняли вопрос: да, блок try-catch действительно подвергается немного служебным , даже если исключение не выдается.

9
ответ дан Yuval Adam 24 November 2019 в 18:01
поделиться

При доступе к файлам EAFP более надежен, чем LBYL, потому что операции, вовлеченные в LBYL, не являются атомарными, и файловая система могла бы измениться между временем, Вы смотрите и время, Вы прыгаете. На самом деле стандартное имя является TOCTOU - Время Проверки, Время Использования; ошибки, вызванные неточной проверкой, являются ошибками TOCTOU.

Рассматривают создание временного файла, который должен иметь уникальное имя. Лучший способ узнать, существует ли выбранное имя файла уже, состоит в том, чтобы попытаться создать его - проверка, что Вы используете опции гарантировать, что Ваша операция перестала работать, если файл действительно уже существует (в терминах POSIX/Unix, флаге O_EXCL к open()). При попытке протестировать, существует ли файл уже (вероятно, использование access()), то между временем, когда это говорит "Нет" и время, Вы пытаетесь создать файл, кого-то, или что-то еще, возможно, создало файл.

С другой стороны, предположите, что Вы пытаетесь считать существующий файл. Ваша проверка, что файл существует (LBYL), может сказать, что "это там", но когда Вы на самом деле открываете его, Вы находите, что "это не там".

и В этих случаях, необходимо проверить заключительную операцию - и в LBYL, автоматически не помог.

(Если Вы смешиваете с SUID или программами SGID, access(), задает различный вопрос; это может относиться к LBYL, но код все еще должен принять во внимание возможность отказа.)

123
ответ дан Jonathan Leffler 24 November 2019 в 18:01
поделиться

В дополнение к относительной стоимости исключений в Python и Java, имейте в виду, что существует различие в философии / отношение между ними. Java пытается быть очень строгим о типах (и все остальное), требуя явных, подробных объявлений класса/сигнатур методов. Это предполагает, что необходимо знать в любой точке, точно какой объект Вы используете и что это способно к выполнению. Напротив, "утиный ввод Python" означает, что Вы не знаете наверняка (и не должен заботиться), каков явный тип объекта, только необходимо заботиться, что это шарлатаны, когда Вы спрашиваете его к. В этом виде общества вседозволенности единственное нормальное отношение должно предположить, что вещи будут работать, но будут готовы иметь дело с последствиями, если они не сделают. Java, естественный строгий, не соответствует хорошо такому случайному подходу. (Это не предназначается, чтобы осуждать или подход или язык, а скорее сказать, что эти отношения являются частью идиомы каждого языка, и копирование идиом между различными языками может часто приводить к неловкости и плохой связи...)

47
ответ дан Jeff Shannon 24 November 2019 в 18:01
поделиться

Исключения обработаны более эффективно в Python, чем в Java, который является [по крайней мере 110] частично , почему Вы видите ту конструкцию в Python. В Java это более неэффективно (с точки зрения производительности) для использования исключений таким образом.

11
ответ дан mipadi 24 November 2019 в 18:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: