Различное NullExceptionHandling между синтаксическим анализом int и double - PullRequest
1 голос
/ 29 февраля 2012

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

Во-первых, когда вы запустите мой пример кода, вы увидите, что нажатие кнопки «ОК» в поле ввода с изменением без какого-либо ввода сохраняет строковое значение, которое кажется нулевым. Однако, когда строка проверяется, она не проверяется как ноль. Почему это?

Во-вторых, когда вы запустите мой пример кода, вы увидите, что нажатие кнопки «Отмена» в поле ввода с изменяемым значением сохраняет значение, которое выглядит как строка, содержащая текст «ноль». Это действительно проверяет как нулевое значение, но строка, содержащая текст "нуль", очевидно, не будет проверяться как нулевое значение. Почему кнопка отмены генерирует строку с текстом «null», когда я думал, что значение нулевой строки было «»?

Наконец, когда вы запустите мой пример кода, вы увидите, что значения, которые тестируются как null, выдают исключение NullPointerException при разборе на двойное число, но они не генерируют исключение NullPointerException, когда они анализируются как int. Почему это?

Мой учитель не мог ответить на эти вопросы. Он считал, что синтаксический анализ в программе примера выполнен арифметически, поэтому целые числа могут вести себя по-разному, потому что они не имеют дело с десятичными точками. Это имеет некоторый смысл для меня, но если это так, почему они по-разному разбираются с нулем, как String answer = ""; и ноль, сгенерированный кнопкой отмены?

Мой пример кода ниже:

    import javax.swing.*; 
    public class NullTest {

public static void main(String[] args) {
    //Demonstrate behavior with doubles.
    throwingDoubles();

    //Demonstrate behavior with integers.
    throwingInts();     
}

public static void throwingDoubles()
{

    //Loops three times so you can test each option.
    for (int i = 0; i < 3; i++)
    {
        JOptionPane.showMessageDialog(null, "Double Tester\nFirst time through click ok without entering text.\nSecond time through click cancel.\nFinally type in null to prove that this string is not treated as a null value.");
        String answer = JOptionPane.showInputDialog(null, "I would think 'answer' would be null if you click ok without entering anything.");
        JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears null here if you don't enter anything, but as a string if you click cancel");

        if (answer==null)
        {
            JOptionPane.showMessageDialog(null, "Double Tester\nTested null");
            JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears the same here.");
        }
        else
        {
            JOptionPane.showMessageDialog(null, "Double Tester\nDid not test null");
            JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appears the same here.");
        }

        try
        {
            double varDoub = Double.parseDouble(answer);    
        }
        catch(NumberFormatException e)
        {
            JOptionPane.showMessageDialog(null, "Double Tester\nThis threw a NumberFormatException");
        }
        catch(NullPointerException e)
        {
            JOptionPane.showMessageDialog(null, "Double Tester\nThis threw a NullPointerException");
        }
        //An early escape clause.
        if (JOptionPane.showConfirmDialog(null, "Run the loop again?")!=JOptionPane.OK_OPTION)
        {
            break;
        }
    }
}


public static void throwingInts()
{

    //Loops three times so you can test each option.
    for (int i = 0; i < 3; i++)
    {
        JOptionPane.showMessageDialog(null, "Int Tester\nFirst time through click ok without entering text.\nSecond time through click cancel.\nFinally type in null to prove that this string is not treated as a null value.");
        String answer = JOptionPane.showInputDialog(null, "Int Tester\nI would think 'answer' would be null if you click ok without entering anything.");
        JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears null here if you don't enter anything, but as a string if you click cancel");

        if (answer==null)
        {
            JOptionPane.showMessageDialog(null, "Int Tester\nTested null");
            JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears the same here.");
        }
        else
        {
            JOptionPane.showMessageDialog(null, "Int Tester\nDid not test null");
            JOptionPane.showMessageDialog(null, "Int Tester\n'" + answer + "'\nIt appears the same here.");
        }

        try
        {
            int varDoub = Integer.parseInt(answer); 
        }
        catch(NumberFormatException e)
        {
            JOptionPane.showMessageDialog(null, "Int Tester\nThis threw a NumberFormatException");
        }
        catch(NullPointerException e)
        {
            JOptionPane.showMessageDialog(null, "Int Tester\nWe never see this code. Why not?");
        }
        //An early escape clause.
        if (JOptionPane.showConfirmDialog(null, "Run the loop again?")!=JOptionPane.OK_OPTION)
        {
            break;
        }
    }
 }

    }

Ответы [ 2 ]

3 голосов
/ 29 февраля 2012

Во-первых, когда вы запустите мой пример кода, вы увидите, что нажатие кнопки «ОК» в поле ввода с изменением без какого-либо ввода сохраняет строковое значение, которое кажется нулевым. Однако, когда строка проверяется, она не проверяется как ноль. Почему это?

Потому что пустая строка не совпадает с нулевой. Когда вы нажимаете «ОК», когда текста нет, вы принимаете пустую строку в качестве значения, которое вы предоставляете. Когда вы нажимаете «Отмена», вы фактически говорите: «Я отказываюсь предоставить значение», поэтому возвращаемое значение задокументировано как:

пользовательский ввод, или ноль, означающий, что пользователь отменил ввод

Далее:

Во-вторых, когда вы запустите мой пример кода, вы увидите, что нажатие кнопки «Отмена» в поле ввода с изменяемым значением сохраняет значение, которое представляется строкой, содержащей текст «ноль». Это действительно проверяет как нулевое значение, но строка, содержащая текст "нуль", очевидно, не будет проверяться как нулевое значение. Почему кнопка отмены генерирует строку с текстом «null», когда я думал, что значение нулевой строки было «»?

Нет, он хранит значение, которое является пустой ссылкой. Нулевая ссылка не такая же, как ссылка на "" или "ноль". Но при конкатенации строк нулевая ссылка преобразуется в «ноль»: "a" + null + "b" в итоге будет иметь вид "anullb".

Очень важно, чтобы вы понимали, как работают ссылки в Java. Ссылка - это эффективный способ навигации к объекту ... а нулевая ссылка - это способ сказать: «Нет объекта для навигации». Если вы рассматриваете переменную со ссылочным значением как лист бумаги с написанным на ней уличным адресом, если значение равно нулю, лист бумаги будет пустым.

Наконец, когда вы запустите мой пример кода, вы увидите, что значения, которые тестируются как null, выдают исключение NullPointerException при разборе на двойное значение, но они не генерируют исключение NullPointerException, когда они анализируются как int. Почему это?

Похоже, что это немного противоречиво в API. Integer.parseInt вместо этого выбрасывает NumberFormatException. Оба ведут себя так, как задокументировано.

0 голосов
/ 29 февраля 2012

Я полагаю, что ваша проблема заключается в следующем:

JOptionPane.showMessageDialog(null, "Double Tester\n'" + answer + "'\nIt appe...
                                                         ^^^^^^

Если answer равно null (пользователь нажал Cancel), сообщение будет отображаться как:

Double Tester
null
Это приложение ...

Однако , если пользователь нажал Ok с пустым полем ввода, answer ссылки пустая строка (""), что дает:

Двойной тестер

Это при ...

Проблема в том, чтоВы путаете строковое значение null ссылки ("null") и пустой строки ("").

...