为什么我抛出NullPointerException

时间:2014-01-06 19:17:32

标签: java exception io

所以这是大学的寒假,我正在努力保持自己的编码,所以我只是编写程序和算法的代码,我们只讨论但从未在课堂上编码。无论如何,我今天正在研究的是一个程序,你给计算机一个乱码,它输出所有可以用这些字母制作的单词(来自我们给出的EnglishWordList文件)。

无论如何,这是我到目前为止的代码:

import java.io.*;
import java.util.*;

public class ProdFinder {
    private HashMap<Character, Integer> prodFinder = new HashMap<Character, Integer>();
    private HashMap<Integer, LinkedList<String>> findWord = new HashMap<Integer,     LinkedList<String>>();

    private static final char[] letters =     {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r',
            's','t','u','v','w','x','y','z'};
    private static final int[] primes =     {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101}; 

    public ProdFinder() throws FileNotFoundException {
        for (int i = 0; i < letters.length; i++) {
            prodFinder.put(letters[i], primes[i]);
        }

        Scanner sc = new Scanner(new File("EnglishWordList.txt"));


        while (sc.hasNextLine()) {
            String str = sc.nextLine();
            int strProd = findProduct(str);

            if (findWord.containsKey(strProd)) {
                LinkedList<String> wordList = findWord.get(strProd);
                wordList.add(str);
                findWord.put(strProd, wordList);
            }
            else {
            LinkedList<String> wordList = new LinkedList<String>();
            wordList.add(str);
            findWord.put(strProd, wordList);
        }
    }

    sc.close();
}

public int findProduct(String x) {
    int product = 1;
    char[] str = x.toCharArray();

    for (Character val: str) {
        product = product*prodFinder.get(val);
    }

    return product;
}

public void descramble(String x) {
    int prod = findProduct(x);

    if (findWord.containsKey(prod)) {
        System.out.println("The words that can be formed from the letters in " + x + " are: " +
                            findWord.get(prod));
    }
    else {
        System.out.println("No words can be formed from the letters in " + x + ".");
    }
}

}

现在,错误起源于我开始将所有数字的主要产品放入我的HashMap的行(试图将每个主要产品映射到其字母乘以该数字的单词的LinkedList。)不知何故,这就是抛出例外,当我注释掉那部分代码并运行findProduct方法时,它可以正常处理任何单词,以便以黄金形式输出lettesr的产品。

有关异常来自哪里的任何想法?

编辑:抱歉,堆栈跟踪如下:

Exception in thread "main" java.lang.NullPointerException
at ProdFinder.findProduct(ProdFinder.java:44)
at ProdFinder.<init>(ProdFinder.java:22)
at Descramble.main(Descramble.java:7)

据我所知,当我尝试在str上调用findProd时,错误就出现了:

int strProd = findProduct(str);

4 个答案:

答案 0 :(得分:7)

问题是ProdFinder.java:44,因为堆栈跟踪指示哪个是

product = product*prodFinder.get(val);

空指针异常是prodFinder没有val的产品/值所以它返回null,程序然后尝试乘以产品。

(任何* null)导致NullPointerException

prodFinder地图没有值的原因可能是因为当所有添加到地图中的单词都是小写字母字符时,单词有一些大写字母,特殊字符或数字

Java调试器是这类问题的一个很好的资源。使用诸如eclipse或netbeans之类的IDE,只需在第44行放置一个断点即可快速找到罪魁祸首用例。

答案 1 :(得分:2)

您目前Map来自NullPointerException。这就是您产生+, -, *, /, ++, --, +, -

的原因

关于unboxing null values的简要介绍:有一组表示基元的对象;这些被称为“包装类”或“盒装类”。它们包括每个具有相关类的原语。

这允许您在泛型集合中使用原始值,因为没有对象,泛型将无法工作。

当Java遇到需要原始值的操作时 - 即某种形式的算术运算符或一元运算符(null),就会发生自动装箱转换。

正在进行装箱和拆箱转换autoboxing。我鼓励你阅读,因为有很多要列出,我会重复已经说过的。

自动装箱的警告是null。请记住,基元具有固定的有限值,并且对象可以存在(具有无限多个值,具体取决于字段数),或者不存在,或者是null。如果您尝试取消NullPointerException的值,则会出现null

现在,关于为什么你从Mapchar[] str = x.toCharArray();x转换为字符数组,将x拉回null,然后再查看映射所有小写字符,并将它们映射到给定的素数值。

如果null中的字符大写,会发生什么?如果它是一个数字怎么办?如果它是一个特殊的角色怎么办?空间?标签?什么不是小写的a-z字母?您在映射中找不到值,它将返回{{1}}。

这也是一个警告 - 在处理盒装基元时,必须采取非常小心,在依赖自动装箱转换时,他们不会处理任何{{1}值或实例。这将导致令人困惑的NPE(像这一样)可能更难跟踪。

答案 2 :(得分:1)

我可以想象以下一行的唯一方法是抛出异常,如果val不在prodFinder

product = product*prodFinder.get(val);

您可能希望在使用之前检查prodFinder.Get的结果

Integer value = prodFinder.get(val);

if(val == null)
    //indicate that you have an error state?
else
    product *= val;

答案 3 :(得分:0)

首先,你应该学习如何使用debuger。如果你不能帮助自己使用一些System.out的

public int findProduct(String x) {
    int product = 1;
    char[] str = x.toCharArray();
    System.out.println("str " + str);
    for (Character val: str) {
        System.out.println("prodFinder " + prodFinder);
        System.out.println("val " + val);
        System.out.println("prodFinder.get(val) " + prodFinder.get(val));
        product = product*prodFinder.get(val);
    }
    return product;
}

对于像这样的文件内容:

Hello
World

输出结果为:

Cmd-$> java Descramble
str Hello
str [C@e80842
prodFinder {f=13, g=17, d=7, e=11, b=3, c=5, a=2, n=43, o=47, l=37 ...
val H
prodFinder.get(val) null
Exception in thread "main" java.lang.NullPointerException
        at ProdFinder.findProduct(Descramble.java:48)
        at ProdFinder.<init>(Descramble.java:23)
        at Descramble.main(Descramble.java:70)

如您所见,对于字母H,返回值为空

数组letters中没有大写字母,因此Map中没有大写字母!

异常发生在

product = product*prodFinder.get(val);

这里jvm试图将地图返回的Integer解包到原始int中以执行乘法。但这是不可能的,因为地图会返回null