Что такое NumberFormatException и как я могу это исправить?
Error Message:
Exception in thread "main" java.lang.NumberFormatException: For input string: "Ace of Clubs"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at set07102.Cards.main(Cards.java:68)
C:\Users\qasim\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 0 seconds)
Мой цикл пока:
while (response != 'q' && index < 52) {
System.out.println(cards[index]);
int first_value = Integer.parseInt(cards[index]);
int value = 0;
//Add a Scanner
Scanner scanner = new Scanner(System.in);
System.out.println("Will the next card be higher or lower?, press q if you want to quit");
String guess = scanner.nextLine();
if(cards[index].startsWith("Ace")) { value = 1; }
if(cards[index].startsWith("2")) { value = 2; }
if(cards[index].startsWith("3")) { value = 3; }
//checking 4-10
if(cards[index].startsWith("Queen")){ value = 11; }
if(cards[index].startsWith("King")){ value = 12; }
if(guess.startsWith("h")){
if(value > first_value){ System.out.println("You answer was right, weldone!"); }
else { System.out.println("You answer was wrong, try again!"); }
} else if(guess.startsWith("l")){
if(value < first_value) { System.out.println("You answer as right, try again!"); }
else { System.out.println("You answer was wrong, try again!"); }
} else { System.out.println("Your was not valid, try again!"); }
scanner.close();
index++;
}//end of while loop
9 ответов
Error Message:
Exception in thread "main" java.lang.NumberFormatException: For input string: "Ace of Clubs"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at set07102.Cards.main(Cards.java:68)
C:\Users\qasim\AppData\Local\NetBeans\Cache\8.1\executor-snippets\run.xml:53: Java returned: 1
средства:
There was an error. We try to give you as much information as possible
It was an Exception in main thread. It's called NumberFormatException and has occurred for input "Ace of Clubs".
at line 65th of NumberFormatException.java which is a constructor,
which was invoked from Integer.parseInt() which is in file Integer.java in line 580,
which was invoked from Integer.parseInt() which is in file Integer.java in line 615,
which was invoked from method main in file Cards.java in line 68.
It has resulted in exit code 1
Другими словами, вы пытались разобрать "Ace of Clubs"
для int
что Java не может сделать с методом Integer.parseInt
, Java предоставила красивую трассировку стека, которая точно скажет, в чем проблема. Инструмент, который вы ищете, это отладчик, а использование точек останова позволит вам проверить состояние вашего приложения в выбранный момент.
Решением может быть следующая логика, если вы хотите использовать синтаксический анализ:
if (cards[index].startsWith("Ace"))
value = 1;
else if (cards[index].startsWith("King"))
value = 12;
else if (cards[index].startsWith("Queen"))
value = 11;
...
else {
try {
Integer.parseInt(string.substring(0, cards[index].indexOf(" ")));
} catch (NumberFormatException e){
//something went wrong
}
}
Что такое Exception
на яве?
Исключением является событие, которое происходит во время выполнения программы и нарушает нормальный поток инструкций программы.
Конструкторы и использование в Integer#parseInt
static NumberFormatException forInputString(String s) {
return new NumberFormatException("For input string: \"" + s + "\"");
}
public NumberFormatException (String s) {
super (s);
}
Они важны для понимания того, как читать трассировку стека. Посмотри как NumberFormatException
брошен из Integer#parseInt
:
if (s == null) {
throw new NumberFormatException("null");
}
или позже, если формат ввода String s
не разбирается:
throw NumberFormatException.forInputString(s);
Что такое NumberFormatException
?
Брошенный, чтобы указать, что приложение попыталось преобразовать строку в один из числовых типов, но что строка не имеет соответствующего формата.
NumberFormatException
extends
IllegalArgumentException
, Это говорит нам, что это более специализированный IllegalArgumentException
, Действительно, он используется для выделения того, что тип аргумента был правильным (String
) содержание String
не является числовым (a, b, c, d, e, f считаются цифрами в HEX и допустимы при необходимости).
Как мне это исправить?
Ну, не исправляйте тот факт, что он брошен. Хорошо, что его бросили. Есть несколько вещей, которые вы должны рассмотреть:
- Можно ли прочитать трассировку стека?
- Это
String
что вызываетException
null
? - Это похоже на число?
- Это "моя строка" или ввод пользователя?
- продолжение следует
Объявление. 1.
Первая строка сообщения - это информация о том, что произошло исключение, и ввод String
что вызвало проблему. Строка всегда следует :
и цитируется ("some text"
). Затем вам будет интересно прочитать трассировку стека с конца, так как первые несколько строк обычно NumberFormatException
конструктор, метод синтаксического анализа и т. д. Затем, в конце, есть ваш метод, в котором вы сделали ошибку. Будет указано, в каком файле он был вызван и в каком методе. Даже линия будет прикреплена. Вот увидишь. Пример того, как читать трассировку стека, приведен выше.
Объявление. 2.
Когда вы видите, что вместо "For input string:"
и вход, есть null
(не "null"
) это означает, что вы пытались передать нулевую ссылку на номер. Если вы действительно хотите обработать как 0 или любое другое число, вас может заинтересовать еще один мой пост на Stackru. Это доступно здесь.
Описание решения неожиданного null
s хорошо описан в потоке Stackru Что такое исключение NullPointerException и как я могу это исправить?,
Объявление. 3.
Если String
что следует за :
и, по вашему мнению, это выглядит как число, это может быть символ, который ваша система не декодирует, или невидимый пробел. очевидно " 6"
не может быть проанализировано, а также "123 "
не может. Это из-за пробелов. Но может случиться так, что String
будет выглядеть "6"
но на самом деле его длина будет больше, чем количество цифр, которые вы можете увидеть.
В этом случае я предлагаю использовать отладчик или хотя бы System.out.println
и распечатать длину String
ты пытаешься разобрать. Если он показывает больше, чем количество цифр, попробуйте передать stringToParse.trim()
к методу разбора. Если это не сработает, скопируйте всю строку после :
и декодировать его с помощью онлайн-декодера. Он даст вам коды всех персонажей.
Есть также один случай, который я недавно обнаружил на Stackru
, что вы можете увидеть, что вход выглядит как число, например "1.86"
и он содержит только эти 4 символа, но ошибка все еще существует. Помните, с помощью #Integer#parseInt# можно анализировать только целые числа. Для разбора десятичных чисел следует использовать Double#parseDouble
,
Другая ситуация, когда номер имеет много цифр. Возможно, он слишком большой или слишком маленький, чтобы уместиться int
или же long
, Вы можете попробовать new BigDecimal(<str>)
,
Объявление. 4.
Наконец, мы подошли к месту, в котором мы согласны, что мы не можем избежать ситуаций, когда пользователь вводит "abc" в виде числовой строки. Зачем? Потому что он может. В счастливом случае это потому, что он тестер или просто выродок. В плохом случае это злоумышленник.
Что я могу сделать сейчас? Ну, Java дает нам try-catch
Вы можете сделать следующее:
try {
i = Integer.parseInt(myString);
} catch (NumberFormatException e) {
e.printStackTrace();
//somehow workout the issue with an improper input. It's up to your business logic.
}
Что такое NumberFormatException
?
Это исключение выдается, чтобы указать, что приложение попыталось преобразовать
string
к одному из числовых типов, но этоstring
не имеет соответствующего формата.
В вашем случае, согласно вашей трассировке стека это исключение было выдано Integer.parseInt(String)
Это означает, что при условии String
не содержит разбора integer
, И все же согласно трассировке стека, это связано с тем, что вы пытались разобрать String
" Туз клубов " как целое число, которое не может работать, поскольку это не String
представление целого числа.
Как это исправить?
Самый простой и общий способ - поймать исключение NumberFormatException
int value = -1;
try {
value = Integer.parseInt(myString);
} catch (NumberFormatException e) {
// The format was incorrect
}
Это будет работать, но перехват исключения происходит медленно, потому что для создания Exception
что дорого, так что если вы можете избежать этого, сделайте это. Более того, вам нужно правильно обработать исключение, что не всегда очевидно.
Или вы могли бы использовать regular expression
сначала проверить, если String
matches
с Integer
но это довольно подвержено ошибкам, так как вы можете легко использовать неправильный regular expression
,
В вашем случае, более подход OO следует использовать вместо того, чтобы иметь дело с String
Например, вы могли бы использовать class
или enum
представлять свои карты вместо использования простых String
потому что это гораздо более подвержено ошибкам, как вы уже заметили.
Так что, если вы решите использовать выделенный класс для вашей карты, ваш код может быть:
public class Card {
private final Rank rank;
private final Suit suit;
public Card(final Rank rank, final Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Rank getRank() {
return this.rank;
}
public Suit getSuit() {
return this.suit;
}
}
Для масти и ранга карты мы можем использовать enum
так как количество рангов и мастей ограничено.
public enum Rank {
ACE(1), TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), HEIGHT(8),
NINE(9), TEN(10), JACK(11), QUEEN(12), KING(13);
private final int value;
Rank(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
}
public enum Suit {
SPADE, HEART, DIAMOND, CLUB
}
затем cards
будет массив Card
вместо массива String
и может быть инициализирован следующим образом:
Rank[] ranks = Rank.values();
Suit[] suits = Suit.values();
Card[] cards = new Card[ranks.length * suits.length];
for (int i = 0; i < ranks.length; i++) {
for (int j = 0; j < suits.length; j++) {
cards[i * suits.length + j] = new Card(ranks[i], suits[j]);
}
}
Если вам нужно перетасовать ваш массив карт, вы можете действовать следующим образом (обратите внимание, что если вы решите использовать List
карточек вместо массива просто используй Collections.shuffle(list)
)
List<Card> allCards = Arrays.asList(cards);
Collections.shuffle(allCards);
allCards.toArray(cards);
Тогда вы сможете напрямую получить доступ к стоимости своей карты с помощью cards[index].getRank().getValue()
без риска получить исключение (кроме IndexOutOfBoundsException
если вы не используете правильный индекс).
Похоже cards[]
массив строк и вы пытаетесь конвертировать Ace of Clubs
в целое число.
int first_value = Integer.parseInt(cards[index]);
java.lang.NumberFormatException
происходит, когда вы пытаетесь проанализировать некоторые входные данные, которые не являются строкой Number.
В вашем случае вы пытаетесь разобрать строку (которая не имеет числа) как целое число. Поскольку это не возможно, возникло исключение NumberFormatException.
int first_value = Integer.parseInt(cards[index]);//cards[index] value should be //number string "123" not "abc"
NumberFormatException - это способ, которым Java должна сказать вам: "Я пытался преобразовать строку в int, и я не смог этого сделать".
В вашем следе исключения вы можете прочитать
Exception in thread "main" java.lang.NumberFormatException: For input string: "Ace of Clubs"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at set07102.Cards.main(Cards.java:68)
По сути, это означает, что в строке 68 вашего кода вы вызываете метод Integer.parseInt, передавая "туз треф" в качестве параметра. Этот метод ожидает целочисленное значение, представленное как String, например, "4", поэтому метод жалуется на выдачу NumberFormatException, потому что "Ace of Clubs" вообще не кажется целым числом.
NumberFormatException
Значит это Integer.parseInt()
не удалось перевести строку в число.
Я бы предложил один из двух вариантов:
Инкапсулируйте карты в виде комбинированного имени (строки)/ значения (int). Используйте значение для сравнения и имя для представления информации пользователю.
Cards[]
затем становится списком карточек, а не строк.Разобрать строки самостоятельно. Что может быть проще, так как вы уже сделали это с
if(cards[index].startsWith("Ace")) { value = 1; }
биты. Вы можете переместить их в функцию под названиемCardToInt()
(или что-то еще), и использовать эту функцию вместоInteger.parseInt()
,
Самое первое, что бросило меня в цикл (без каламбура), было то, что вы ограничивали значение 1-13, когда оно должно быть 0-52. Также с вашей логикой значение всегда было выше. Лучший подход с генератором чисел. Вот мой код с использованием генератора чисел (или Java Random):
public static void main(String[] args) {
String[] cards = { "Ace of Clubs", "1 of Clubs", "2 of Clubs",
"3 of Clubs", "4 of Clubs", "5 of Clubs", "6 of Clubs",
"7 of Clubs", "8 of Clubs", "9 of Clubs", "10 of Clubs",
"Queen of Clubs", "King of Clubs", "Ace of Diamonds",
"1 of Diamonds", "2 of Diamonds", "3 of Diamonds",
"4 of Diamonds", "5 of Diamonds", "6 of Diamonds",
"7 of Diamonds", "8 of Diamonds", "9 of Diamonds",
"10 of Diamonds", "Queen of Diamonds", "King of Diamonds",
"Ace of Hearts", "1 of Hearts", "2 of Hearts", "3 of Hearts",
"4 of Hearts", "5 of Hearts", "6 of Hearts", "7 of Hearts",
"8 of Hearts", "9 of Hearts", "10 of Hearts",
"Queen of Hearts", "King of Hearts", "Ace of Spades",
"1 of Spades", "2 of Spades", "3 of Spades", "4 of Spades",
"5 of Spades", "6 of Spades", "7 of Spades", "8 of Spades",
"9 of Spades", "10 of Spades", "Queen of Spades",
"King of Spades" };
Scanner scanner = new Scanner(System.in);
Random rand = new Random();
String response = "";
int index = 0;
int value = 0;
while (!response.equals("q") && index < 52) {
// set next card value based on current set of cards in play
if (cards[index].endsWith("Clubs")) {
value = rand.nextInt(12);
}
if (cards[index].endsWith("Diamonds")) {
value = rand.nextInt(12) + 13;
}
if (cards[index].endsWith("Hearts")) {
value = rand.nextInt(12) + 26;
}
if (cards[index].endsWith("Spades")) {
value = rand.nextInt(12) + 39;
}
// display card too user (NOTE: we use the random number not the index)
System.out.println("Card is: " + cards[value]);
// ask user what well the next card be
System.out.println("Will the next card be higher or lower?, press q if you want to quit");
response = scanner.nextLine();
// display if user was right (NOTE: compared the random number to the current index)
// ignore incorrect response and just continue
if ((value > index && response.startsWith("h")) || (value < index && response.startsWith("l"))) {
System.out.println("You answer was right, well done!");
} else {
System.out.println("You answer was wrong, try again!");
}
// continue loop
index++;
}
}
Что касается NumberFormatException, я считаю, что Николас Филотто хорошо объяснил это.
int first_value = Integer.parseInt(cards[index]);
во время написания вышеприведенного заявления вы пытаетесь разобрать "туз треф" как число.
Вы можете использовать следующий метод, чтобы проверить, может ли любая строка быть проанализирована как Integer:
boolean tryParseInt(String value) {
try {
Integer.parseInt(value);
return true;
} catch (NumberFormatException e) {
return false;
}
}
Относительно вашего вопроса, что такое NumberFormatException: он выдается, чтобы указать, что приложение попыталось преобразовать строку в один из числовых типов, но строка не имеет соответствующего формата. (ссылка - http://docs.oracle.com/javase/7/docs/api/java/lang/NumberFormatException.html).
Исключение входит в ваш код, где вы преобразуете строку в целое число:
int first_value = Integer.parseInt(cards[index]);
где вы передаете строку как "туз треф", которую невозможно преобразовать как целое число, поэтому выдается исключение числового формата. Ты можешь использовать,
try {
....
// Your Code
....
}
catch(NumberFormatException e)
{
e.getMessage(); //You can use anyone like printStackTrace() ,getMessage() to handle the Exception
}