Подтвердить что ты не робот

Как узнать, какая переменная является виновником в блоке try?

В определенном блоке try у меня есть две переменные String, которые могут вызвать NumberFormatException, когда я пользователь Integer.parseInt(string1) и Integer.parseInt(string2). Вопрос: если я catch исключение, как узнать, какая строка является нарушителем спокойствия? Мне нужно получить имя переменной нарушителя.

Вот пример кода:

public class test {
    public static void main(String[] args) {
        try {
            String string1 = "fdsa";
            String string2 = "fbbbb";
            Integer.parseInt(string1);
            Integer.parseInt(string2);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        }
    }

И метод e.printStackTrace() не говорит мне имя переменной; это просто говорит мне содержание нарушителя спокойствия.

java.lang.NumberFormatException: для строки ввода: "fdsa" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)   в java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) в test.main(test.java:9) at sun.reflect.NativeMethodAccessorImpl.invoke0 (собственный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)   в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)   в java.lang.reflect.Method.invoke(Method.java:498) в com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

Процесс завершен кодом выхода 0

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

System.out.println(troubleMakerName + "is wrong!")

В моих Требованиях пользователь должен ввести

fd=(fileName,maxLength,minLength)

тогда я проанализирую входную строку и создаю некоторые ответы. Поэтому я хотел бы проверить, будут ли maxLength и minLength бросать NumberFormatException. В этом случае, если minLength что-то не так, тогда мне нужно запросить у пользователя, что minLength ошибочна.

4b9b3361

Ответ 1

У вас есть XY-Problem.

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

String fileName, maxLengthInput, minLengthInput;
int maxLength, minLength;

List<String> errors = new ArrayList<>();

try {
    maxLength = Integer.parseInt(maxlengthInput);
} catch (NumberFormatException nfe) {
    errors.add("Invalid input for maximum length, input is not a number");
}

try {
    minLength = Integer.parseInt(minlengthInput);
} catch (NumberFormatException nfe) {
    errors.add("Invalid input for minimum length, input is not a number");
}

// show all error strings to the user

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

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

Если задействовано больше входных данных, вы можете реорганизовать это в цикл.

Ответ 2

Используйте 2 отдельных блока try, catch для разбора двух входов для каждой переменной. Затем создайте сообщение проверки работоспособности внутри каждого блока catch.

        String string1 = "fdsa";
        String string2 = "fbbbb";
        try {
            Integer.parseInt(string1);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            **//Please provide a valid integer for string1**
        }
        try {
            Integer.parseInt(string2 );
        } catch (NumberFormatException e) {
            e.printStackTrace();
           **//Please provide a valid integer for string2** 
        }

Ответ 3

Я хотел бы написать собственный метод parseInt:

public static int parseInt(String s, 
                           Supplier<? extends RuntimeException> supplier) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        throw (RuntimeException)supplier.get().initCause(e);
    }
}

Как я знаю, мы не можем читать имя переменной путем отражения, поэтому я просто передаю литерал String:

parseInt(string1, () -> new NumberFormatException("string1"));

Я оставлю исходный ответ и предоставил версию, которая была обсуждена в комментариях. Но пока я смущен, почему Поставщик является излишним.

public static int parseInt(String s, String message) {
    try {
        return Integer.parseInt(s);
    } catch (NumberFormatException e) {
        throw (NumberFormatException)new NumberFormatException(message).initCause(e);
        // throw new IllegalArgumentException(message, e);
    }
}

Его вызов выглядит как

parseInt(string1, "string1");

Ответ 4

Перед выполнением операции вы можете написать простую функцию isInteger(), которая может вернуть вам логическое значение. Хорошую реализацию можно найти в этой теме. Это использует радиус значения и итерации, если он является int и весьма удобен. Определить, является ли String целым в Java Простой if условный тогда может найти, какое значение является изгоем в аргументе

Ответ 5

Просто используйте другой catch для другого оператора

public class test 
{
    public static void main(String[] args) 
    {
        String string1 = "fdsa";
        String string2 = "fbbbb";

        try 
        {
            Integer.parseInt(string1);
        } 
        catch (NumberFormatException e) 
        {
            System.out.println("string1 is the culprit");
            e.printStackTrace();
        }

        try 
        {
            Integer.parseInt(string2);
        } 
        catch (NumberFormatException e) 
        {
            System.out.println("string2 is the culprit");
            e.printStackTrace();
        }
    }
}

Ответ 6

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

public class test {
    public static void main(String[] args) {
        String string1 = returnString("fdsa", "string1");
        String string2 = returnString("fbbbb", "string2");
    }

    private string returnString(String input, String varName) {
        String str = "";
        try {
            str = input;
            Integer.parseInt(str);
        } catch (NumberFormatException e) {
            System.out.println("Error processing " + varName);
        }
        return str;
    }
}

Ответ 7

Я удивлен, что никто не предложил что-то вроде этого:

public class test {
public static void main(String[] args) {
    String errorContext;

    try {            
        String string1 = "fdsa";
        String string2 = "fbbbb";

        errorContext = "string1";
        Integer.parseInt(string1);

        errorContext = "string2";
        Integer.parseInt(string2);
    } catch (NumberFormatException e) {
        System.out.println(errorContext + " is wrong!")
        e.printStackTrace();
    }
    }
}

Это очень простое решение - упрощенное, некоторые скажут - но оно также довольно ясное и надежное.

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

Ответ 8

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

public class test {

    private static final Pattern pattern = Pattern.compile("\\d+");
    public static void main(String[] args) {
            String string1 = "fdsa";
            String string2 = "fbbbb";
            if (pattern.matcher(string1).matches()) {
                Integer.parseInt(string1);
            } else {
                //string1 is not an integer
            }
            ...
    }
}

Или вы могли просто написать

boolean errorInLineOne = !pattern.matcher(string1).matches();
...

Ответ 9

Это довольно упрощенно, но вот мое решение..

public class test
{
    public static int tryParseInt(String str) throws Exception
    {
        try
        {
            return Integer.parseInt(str);
        }
        catch(Exception e)
        {
            System.err.println("tryParseInt: couldn't parse '"+str+"'");
            throw e;
        }
    }

    public static void main(String[] args)
    {
        try
        {
            String string1 = "fdsa";
            String string2 = "fbbbb";

            tryParseInt(string1);
            tryParseInt(string2);
        }
        catch (NumberFormatException e)
        {
            e.printStackTrace();
        }
    }
}