Вопрос по null, coding-style, exception, java – Бросить исключение или вернуть ноль

5

Если у меня есть функция ниже, с двумя вариантами

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    return null;
}

private MyObject findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return pieces[i];
        }
    }
    throw new NoSuchFieldError("No blank piece found!");
}

Из этого метода я знаю, что этоshould always return an object один из «кусочков»; всегда естьisBlank() == true возвращаемое значение null в конце просто для того, чтобы угодить компилятору. Так как это так, и мой код не будет работать в любом случае, если он вернул значение null, правильно ли это, пожалуйста, чтобы сгенерировать исключение?

Мои варианты:

return null and the app will get a NullPointerException in some edge case return null and wrap the use of the method with (myObject != null) checks throw an exception which will blow it up at runtime

Я предполагаю, что я спрашиваю, является ли это правильным местом для создания исключения? то есть я ничего не могу с этим поделать, если он попадет в ситуацию. Является ли это классифицированным как «исключительный»? или я должен проверить, что возвращает мой метод (что делает мой код ужасным). Если я знаю, что он не должен возвращать ноль, тогда я должен выбросить исключение, верно?

Кроме того, как бы я выбрал, какое исключение, или расширил бы одно и бросил свое собственное?

@missingfaktor Я пишу код в Android, поэтому не могу использовать другие тяжелые фреймворки Blundell
Является ли «ни один» предложение не привлекательно? :-) missingfaktor
Понял. Что бы это ни стоило, эта конкретная абстракция не такая уж и тяжелая, и вы можете добавитьonly the required part если вы найдете это полезным. missingfaktor
Чтобы помочь выбрать исключение:wuhrr.wordpress.com/2007/11/22/java-exceptions-list Blundell
Ну, я считаю, что исключение - это лучшее, что нужно сделать. Вы не должны возвращать ноль никогда. Вместо этого вы можете вызвать этот метод в блоке try-catch и убедиться, что вы делаете что-то в блоке catch при возникновении исключения. Что касается передового опыта, вы также можете сделать так, чтобы родительский класс, вызывающий этот метод, передавал исключение в восходящем направлении, которое при необходимости может отображаться на уровне пользовательского интерфейса. Radioactive

Ваш Ответ

9   ответов
1

рмации, потерянной при просмотре контракта. Потребитель может не знать, в чем причина неправильного ответа, если получить нулевое значение от производителя.

При просмотре вашего первого кода, есть две ситуации, когда внешний код получает исключение NULLPointerException: 1. штук ноль 2. У штук не было такого элемента

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

И поговорим о разнице между возвращаемым значением nullObject (не нулевым) и исключением: основное отличие - ВЕРОЯТНОСТЬ, что означает: 1. Если пустая ситуация с большей вероятностью, она должна вернуть nullObject, чтобы ВСЕ внешний код мог / должен обрабатывать их явно. 2. Если в пустой ситуации меньше вероятность, почему бы не сгенерировать исключение, чтобы функция окончательного вызова могла обработать его напрямую.

0

Нулевой объект.

Provide an object as a surrogate for the lack of an object of a given type. The Null Object provides intelligent do nothing behavior, hiding the details from its collaborators

Таким образом, в этом случае вам не придется использовать исключения или возвращать ноль. Вы всегда можете вернуть предполагаемый тип возвращаемого объекта. Хитрость в том, что вам нечего возвращать, а не возвращатьnull или бросив исключение, вы можете вернутьNull object это тот же тип, что и предполагаемый тип возвращаемого значения.

этодокументация имеет несколько примеров и описаний. И имеет такой же случай, как у вас, решается по шаблону дизайна.

public class CustomerFactory {

  public static final String[] names = {"Rob", "Joe", "Julie"};

  public static AbstractCustomer getCustomer(String name){   
    for (int i = 0; i < names.length; i++) {
       if (names[i].equalsIgnoreCase(name)){
         return new RealCustomer(name);
       }
    }
    return new NullCustomer();
  }
}
4

Is it a good idea to have your program blow up at some point after this method returned an unexpected value (i.e. null)? What exactly will be hidden if you mask out the null return value? Is it a good idea to blow up immediately, just because there was a wrong value?

Лично я бы выбрал вариант 2 или 3, в зависимости от того, что мне больше нравится ответ на вопрос 2 или 3. Вариант 1 определенно является плохой идеей, особенно если это не должно происходить. Если программа выдает NPE после того, как ваша функция вернулась, вам будет трудно выяснить, гдеnull пришли из. Особенно, если это происходит через несколько месяцев после того, как вы закончили работу над этой конкретной функцией.

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

10

m asking is, is this the correct place to throw an exception?

Если бы это былоexceptional Ситуация, то да. Если возможность не найти ничего, что соответствует критериямexpected тогда ситуация неexceptional и ты должен вернутьсяnull.

0

performance ваша забота,Exceptions are way slower than returning null

Посмотрите на этот код:

class Main {
    public static void main(String[] args) {
        testException();
        testNull();
    }

    public static void testException() {
        long st = System.currentTimeMillis();
        for(int i=0;i<10000000;i++) {
            try{
                exp();
            } catch(Exception e) {

            }
        }
        long et = System.currentTimeMillis();
        System.out.println("Time taken with exceptions : "+(et-st));
    }

    public static void testNull() {
        long st = System.currentTimeMillis();
        for(int i=0;i<10000000;i++) {
            returnNull();
        }
        long et = System.currentTimeMillis();
        System.out.println("Time taken with null : "+(et-st));
    }

    public static void exp() throws Exception {
        throw new Exception();
    }

    public static Object returnNull() {
        return null;
    }
}

Результаты на моей машине:

Time taken with exceptions : 7526
Time taken with exceptions : 5

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

Вам придется сделатьPerformance vs Maintainability / Readability компромисс.

Подробнее об этомВот

0

ата, вы должны вызвать исключение как запасной вариант. (Случай 2sd в вашем примере)

В конце концов, вы можете объявить свой собственный тип (класс) исключения.

0

should always return an object или жеreturn null

the app will get a NullPointerException in some edge case
эти два противоречивы.

Если вы действительно уверены, что у вас всегда естьpieces[i].isBlank() затем броситьIllegalStateException

В противном случае обрабатывать дело в соответствии с вашими требованиями.

4

RuntimeException для обозначения «исключительного» Ситуация, которая не должна была возникнуть.IllegalStateException вероятно, отвечает всем требованиям. Убедитесь, что вы включили сообщение с любой информацией, которая поможет вам найти ошибку, если она когда-либо будет выдана.

Я не уверен, что согласен с "не могу восстановить" часть.
@HovercraftFullOfEels - Как вы рекомендуете это должно быть сформулировано?
Я бы удалил & quot; из которого ваша программа не может восстановиться & quot; часть.
0

Maybe (также известен какOption) тип данных, о котором я только что говорил вдругой ответ Некоторое время назад

Этот тип данныхдоступен вФункциональная Java.

Usage:

private Option<MyObject> findBlank() {
    for (int i = 0; i < pieces.length; i++) {
        if(pieces[i].isBlank()){
            return Option.some(pieces[i]);
        }
    }
    return Option.none();
}

Sidenote:

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

Неудивительно,Функциональная Java уже имеет это.

Давайте на минуту предположим, чтоpieces этоfj.data.List, Тогда ваш метод может быть переписан как:

private Option<MyObject> findBlank() {
  return pieces.find(new F1<MyObject, Boolean>() {
    public Boolean f(MyObject p) {
      return p.isBlank();
    }
  });
}

Another sidenote:

Возможно, приведенный выше код выглядит довольно мрачно.IntelliJ IDEA "сворачивание укупорочного средства" может помочь.

Найти больше мясаhere.

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