Можно ли упростить выдачу ошибок для комбинированного оператора IF?

Так скажи, у меня есть if утверждение как if (bool1 && bool2) {},
Я хочу отображать различные сообщения об ошибках в зависимости от того, какой из этих логических значений не удалось. Обычно я бы сделал что-то вроде:

if (bool1) {
    if (bool2) {
        // do something
    } else {
        // throw error for bool2 failing
    }
} else {
    // throw error for bool1 failing
}

Теперь я точно знаю, что bool1 не удалось, но bool2 может быть и плохим. Поэтому я бы использовал что-то вроде:

if (bool1 && bool2) {
    // do something
} else {
    if (!bool1) {
        // throw error for bool1 failing
    }
    if (!bool2) {
        // throw error for bool2 failing
    }
    ...
}

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

// continuing on the dots of the above code block
if (!bool1 && !bool2) {
    // throw error for both failing
}

Есть ли более эффективный метод для этого?


Изменить: Поскольку все данные ответы являются жизнеспособными, а что лучше, субъективно, я не собираюсь принимать любой как "ответ". Не забудьте выбрать метод / ответ, который лучше всего подходит для ваших собственных нужд.
Спасибо всем за ваши предложения.

9 ответов

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

StringBuilder errorMsg = new StringBuilder();

if (!bool1) {
    errorMsg.append("bool1 condition failed\n");
}

if (!bool2) {
    errorMsg.append("bool2 condition failed\n");
}

if (!bool3) {
    errorMsg.append("bool3 condition failed\n");
}

// etc

if (errorMsg.length() > 0) {
    throw new SomeException(errorMsg.toString());
}

// safely execute your code here

Проверьте полезное StringBuilder класс документов для дальнейшего использования.

Мне не ясно, каков ваш сценарий, но, возможно, я бы подошел к вашей проблеме следующим образом (аналогично ответу DAB):

    List<String> errors = new ArrayList<String>();
    if(!bool1){
        errors.add("Error message 1");
    }

    if (!bool2) {
        errors.add("Error message 2");
    }

    // other errors

    if(!errors.isEmpty()){
        throw new Exception(buildErrorsMessage(errors));
    }

Нет, я не знаю, как это сделать. Способ сделать это более эффективно - это реструктурировать ваш код, так что вам не нужно слишком глубоко вкладывать if-предложения.

Вы могли бы сделать что-то вроде этого:

public static <T extends Throwable> void throwIf(boolean condition, Supplier<T> e) throws T {
    if(condition) throw e.get();
}
throwIf(!bool1 && !bool2, () -> new Exception("big oops"));
throwIf(!bool1, MyException::new);
throwIf(!bool2, () -> new Exception("oops"));
throwIf(!bool3, Error::new);

// do something

Я бы сделал это так

String error=null;
if(!bool)
    error="Something";
else if(!bool2)
    error="Other message";
else if(!bool3) 
    error="failed??";

// ...
if(error!=null) {
   throw new Exception(error);
}

Если вам нужно выдавать различные типы исключений, вы можете иметь ошибку типа Exception вместо строки, а затем создать исключение в if(! Bool1)

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

package com.idfbins.questions;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class maptest {

    public static void main(String[] args) {
        Map<String, Boolean> maparini = new HashMap<String, Boolean>();
        maparini.put("variable1", true);
        maparini.put("variable2", true);
        maparini.put("variable3", true);
        maparini.put("variable4", true);
        maparini.put("variable5", true);

        System.out.println("All are true? " + allAreTrue(maparini));
        System.out.println("All are false? " + allAreFalse(maparini));
        System.out.println("Errors for all true: ");
        errorsForTrue(maparini);
        System.out.println("Errors for all false: ");
        errorsForFalse(maparini);

    }

    public static boolean allAreTrue(Map<String, Boolean> maparini){
        return !maparini.containsValue(false);
    }

    public static boolean allAreFalse(Map<String, Boolean> maparini){
        return !maparini.containsValue(true);
    }

    public static void errorsForFalse(Map<String, Boolean> maparini){
        for(Entry<String, Boolean> mapariniEntry : maparini.entrySet()){
            if(mapariniEntry.getValue()){
                System.out.println(mapariniEntry.getKey() + " was true!");
                //You can construct a string to throw in an exception here
            }
        }
    }

    public static void errorsForTrue(Map<String, Boolean> maparini){
        for(Entry<String, Boolean> mapariniEntry : maparini.entrySet()){
            if(!mapariniEntry.getValue()){
                System.out.println(mapariniEntry.getKey() + " was false!");
                //You can construct a string to throw in an exception here
            }
        }
    }

}

Что вы не измените свой, если?

if(!bool1)
{
    if(!bool2)
    {
        error both
    }
    error bool1
}
else if(!bool2)
{
     error 2
}
else
  do somthing

Вот как я обычно это делаю...

    String error=null;

    if( a )
    {
        error="Error a";
    }
    else if( b )
    {
        error="Error b";
    }
    else if( c )
    {
        error="Error c";
    }

    if( error!=null )
    {
        throw new Exception(error);
    }
    if (!bool1 && !bool2) {
        // throw error for bool1 && bool2 failing
    } else if (!bool1) {
        // throw error for bool1 failing
    } else {
        // throw error for bool2 failing
    }
Другие вопросы по тегам