Как узнать, какая переменная является виновником в блоке 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 ошибочна.
Ответы
Ответ 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();
}
}
}