Search code examples
javaparseint

Integer.parseInt sometimes has NumberFormatException


I have a program where a user enters a number (which will be an integer) into a JTextField. The program that uses Integer.parseInt() to get whatever is typed into the JTextField. Usually the program runs smoothly with no issues. However, every now and then I will get a NumberFormatException even among the same numbers. For instance, on one run of the program I could type in 5 into the JTextField. On another run I could do the same and type 5 into the JTextField and I would get a NumberFormatException. I didn't change the code or anything so I don't understand why this is happening. Here is a portion of the code:

JPanel an = new JPanel(new GridBagLayout());
JLabel assignNamesLabel = new JLabel("Assign Book Names");
JLabel bookNumberLabel = new JLabel("Book Number");
JLabel nameOfBookLabel = new JLabel("Book Name");
final JTextField bookNumber = new JTextField(20);
final JTextField bookName = new JTextField(20);
JButton assignName = new JButton("Assign");

assignNamesLabel.setFont(f);
gbc.gridx = 1;
gbc.gridy = 0;
an.add(assignNamesLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
an.add(bookNumberLabel, gbc);
gbc.gridx = 1;
an.add(bookNumber, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
an.add(nameOfBookLabel, gbc);
gbc.gridx = 1;
an.add(bookName, gbc);
gbc.gridy = 3;
gbc.gridx = 1;
an.add(assignName, gbc);

assignNamesPanel.add(an, BorderLayout.CENTER);

tabs.addTab("Assign Book Names", assignNamesPanel);
// function
assignName.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        int i = Integer.parseInt(bookNumber.getText());
        if (shelf.book[i] == null) {
            shelf.book[i] = new shelf();
        }
        shelf.book[i].bookName = bookName.getText();
        bookNumber.setText("");
        bookName.setText("");
        bookNumber.requestFocus();
    }
});

I get the error sometimes at:

int i = Integer.parseInt(bookNumber.getText());

Solution

  • I would add some logic to validate that it is a number before attempting to parse it. Since primitive integers cannot be null, a -1 is returned. You can check so see if the processed value is valid as well. Of course, -1 is only an example. If you need -1 to be valid, just make the default Integer.MIN_VALUE or something.

    Catching the error is the prefered way i.e. parseIntSafelyWithCatch(). You could also use an extraction method i.e. parseIntSafelyWithExtraction() as an alternative to avoid exception handling.

    NumberValidator

    public class NumberValidator {
        public static final String INT_REGEX = "[^-?0-9]+";
        public static final String CONTAINS_INT_REGEX = "^.*[-?0-9]+.*$";
    
        public static int parseIntSafelyWithCatch(String value) {
            if (value == null || value.isEmpty()) {
                return -1;
            }
            try {
                return Integer.parseInt(value.trim());
            } catch (NumberFormatException e) {
                return -1;
            }
        }
    
        public static int parseIntSafelyWithExtraction(String value) {
            if (value == null || value.isEmpty()) {
                return -1;
            }
            if (value.matches(CONTAINS_INT_REGEX)) {
                return Integer.parseInt(value.replaceAll(INT_REGEX, ""));
            }
    
            return -1;
        }
    
        public static boolean isValidNumber(int value) {
            return value != -1;
        }
    
        public static void main(String[] args) {
            System.out.println(parseIntSafelyWithCatch("")); // -1
            System.out.println(parseIntSafelyWithCatch("42")); // 42
            System.out.println(parseIntSafelyWithCatch(" 42")); // 42
            System.out.println(parseIntSafelyWithCatch(" 42 ")); // 42
            System.out.println(parseIntSafelyWithCatch("-42")); // -42
        }
    }
    

    Usage

    int i = NumberValidator.parseIntSafelyWithCatch(bookNumber.getText());
    boolean isValid = NumberValidator.isValidInteger(i);