Исключение java.lang.NumberFormatException: для входной строки: «»

#java #jtextfield #number-formatting

#java #jtextfield #форматирование чисел

Вопрос:

При запуске этого кода:

 JTextField ansTxt;
...
ansTxt = new JTextField(5);
String aString = ansTxt.getText();
int aInt = Integer.parseInt(aString);
  

Почему я получаю эту ошибку?

Исключение в потоке «AWT-EventQueue-0» java.lang.NumberFormatException: для входной строки: «»

Обновить:

 JTextField ansTxt;
ansTxt = new JTextField(5);

ansTxt.addKeyListener(new KeyAdapter() {
   public void keyReleased(KeyEvent e) {
    ansTxt = (JTextField) e.getSource();
    String aString = ansTxt.getText().trim();
    int aInt = Integer.parseInt(aString);
   }
}
  

Комментарии:

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

2. Я просто не понимаю, почему я получил ошибку.

3. Когда возникает ошибка? Вы не вводите, скажем, «5», а затем нажимаете пробел?

4. Нет, я просто ввел любое число, не нажимая backspace..it автоматически переключается на другой экран.

5. @Jessy Ты проверял с помощью отладчика, что такое строка, когда ты вводил?

Ответ №1:

Целочисленный аргумент для конструктора JTextField на самом деле является шириной в количестве столбцов. Из документов:

public JTextField(int columns)

Создает новое пустое текстовое поле с указанным количеством столбцов. Создается модель по умолчанию, а начальной строке присваивается значение null.

Создав ее с помощью

 ansTxt = new JTextField(5);
  

по сути, вы получите пустое текстовое поле (немного шире, чем если бы вы создали его с помощью конструктора без аргументов). Если вы хотите, чтобы она содержала строку «5», вы должны написать

 ansTxt = new JTextField("5");
  

Обновить:

IIRC, вы получите одно событие для keyDown, одно для keyTyped и одно для keyUp. Предположительно, текстовое поле еще не было обновлено при событии keyDown.

В любом случае я предлагаю вам инкапсулировать Integer.parseInt в

 try { ... } catch (NumberFormatException e) { ... }
  

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

—>

Комментарии:

1. извините за путаницу .. да, я установил ширину как 5 … Я попросил пользователя ввести любую строку в JTextField, а не конкретно 5… Я пробовал trim(), но это не работает.

2. @Jessy В вашем коде в вопросе у пользователя нет возможности что-либо сделать, поскольку JTextField создается и немедленно анализируется. Это ошибка в приведенном выше коде или также в вашем приложении?

3. @Jessy Я не уверен, что вы имеете в виду, но это не то, что делает опубликованный вами код. Он создает новое текстовое поле, извлекает содержащийся в нем текст (который по умолчанию является пустой строкой) и пытается преобразовать его в целое число. getText не запрашивает у пользователя текст, он просто извлекает текущий текст из текстового поля

4. ansTxt = (JTextField) e.getSource(); Строка aString = ansTxt.getText().trim(); int aInt = Целое число.parseInt(строка);

5. Вам нужно (обновить вопрос или создать новый вопрос) И (предоставить больше контекста). Откуда e берется?

Ответ №2:

Вы пытаетесь проанализировать пустую строку как int, что не работает. Какой int следует «» анализировать как? В JTextField должен быть текст, который можно разобрать.

 ansTxt.addKeyListener(new KeyAdapter() {
    public void keyReleased(KeyEvent e) {
        ansTxt = (JTextField) e.getSource();
        try {
            int aInt = Integer.parseInt(ansTxt.getText());
            //Do whatever you want with the int
        } catch(NumberFormatException nfe) {
            /*
             * handle the case where the textfield 
             * does not contain a number, e.g. show
             * a warning or change the background or 
             * whatever you see fit.
             */
        }
    }
}
  

Вероятно, также не стоит устанавливать ansTxt внутри KeyAdapter. Я бы посоветовал вам использовать для этого локальную переменную. Это также упрощает перемещение адаптера в «реальный» класс вместо анонимного.

Ответ №3:

Используйте метод trim() .

 int m=Integer.parseInt(txtfield.getText().trim());  
  

trim() метод удалит любую строку, привязанную к числу.

Ответ №4:

Ваше KeyAdapter будет запущено до того, как ваше ansText обработает ключевое событие. На самом деле, вы можете e.consume() вообще запретить ansText ее обработку. Таким образом, при первом нажатии и отпускании клавиши ansText.getText() все равно будет "" . Вот почему вы получаете исключение в первый раз. При двойном нажатии цифровой клавиши должно сработать во второй раз.

Ответ №5:

Попробуйте внедрить библиотеку Apache «commons Lang» в свой проект, и для вашей последней строки вы можете сделать

 int aInt = 0;
if(StringUtils.isNotBlank(aString) amp;amp; StringUtils.isNumeric(aString) ){
    aInt = Integer.parseInt(aString);
}
  

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

правка2: согласно комментариям Томаса ниже. Я запустил тест, чтобы сравнить способ try / catch и StringUtils для решения этой проблемы. Тест был выполнен 5 миллионов раз для каждого. Среднее время попытки / перехвата составило 21 секунду. Среднее время для строк составило 8 секунд. Таким образом, использование StringUtils для большой нагрузки значительно быстрее. Если нагрузка на код невелика, вы практически не заметите разницы. Выполненный тест был

 try{
   result = Integer.parseInt(num);
}catch(NumberFormatException ex){
   result = -1;
}
  

против

 if(StringUtils.isNotBlank(num) amp;amp; StringUtils.isNumeric(num)){
   result = Integer.parseInt(num);
}else{
   result = -1;
}
  

каждый цикл генерирует новую случайную строку из 10 цифр, чтобы избежать какой-либо оптимизации в циклах инструкции if. Это добавило 6-7 секунд накладных расходов.

Комментарии:

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

2. @Thomas Для перехвата исключения требуются служебные данные. Выполнение проверки IsNumeric() в StringUtils также сопряжено с накладными расходами. Итак, все сводится к удобству сопровождения. Я предпочитаю не перехватывать каждое исключение, которое может быть вызвано, и проверять свои типы перед синтаксическим анализом, чтобы избежать исключения, другие могут этого не делать. Это зависит от предпочтений.

3. Это происходит в интерактивном графическом интерфейсе, реагирующем на нажатия клавиш. Затраты на перехват исключения в вашем тесте составили 0,0000026 секунды на нажатие клавиши. Я не думаю, что пользователь заметит разницу во времени отклика в 0,0026 миллисекунд

4. Да, для небольших приложений разница между любым из наших методов очень мала. Я всегда слышал, что при использовании операторов catch были накладные расходы, но никогда не знал, насколько они велики. Я использовал эту проблему в качестве упражнения, чтобы выяснить это для себя. Для этого вопроса разница будет очень незначительной, но в более крупном приложении, более чувствительном ко времени, приведенный выше анализ мог бы помочь.