[英]Why am I throwing a NullPointerException
所以这对大学来说是一个寒假,而我正试图在编码上保持敏锐,所以我只是编写程序和算法的代码,我们只讨论但从未在课堂上编码。 无论如何,我今天正在研究的是一个程序,你给计算机一个扰乱的单词,它输出所有可以从这些字母中产生的单词(来自我们给出的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);
问题是ProdFinder.java:44,因为堆栈跟踪指示哪个是
product = product*prodFinder.get(val);
空指针异常是prodFinder没有val的产品/值,因此它返回null,程序然后尝试乘以产品。
(任何* null)导致NullPointerException
prodFinder地图没有值的原因可能是因为当所有添加到地图中的字都是小写字母字符时,该单词有一些大写字母,特殊字符或数字
Java调试器是这类问题的一个很好的资源。 使用诸如eclipse或netbeans之类的IDE,只需在第44行放置一个断点即可快速找到罪魁祸首用例。
您当前正在从Map
取消装箱null
值 。 这就是导致NullPointerException
。
关于自动装箱的简要介绍:有一组表示原语的对象; 这些被称为“包装类”或“盒装类”。 它们包括具有相关类的每个基元。
这允许您在泛型集合中使用原始值,因为泛型在没有对象的情况下将无法工作。
当Java遇到需要原始值的操作时 - 即某种形式的算术或一元运算符( +, -, *, /, ++, --, +, -
),就会发生自动装箱转换。
根据规范进行拳击和拆箱转换。 我鼓励你阅读,因为有很多要列出的内容,我会重复已经说过的内容。
对自动装箱的警告是null
。 请记住,基元具有固定的有限值,并且对象可以存在(具有无限多个值,具体取决于字段数),或者不存在,或者为null
。 如果尝试取消装入null
的值,则会发生NullPointerException
。
现在,至于为什么要从Map
拉回null
: char[] str = x.toCharArray();
将任何x
转换为字符数组,然后查看所有小写字符的映射,并将它们映射到给定的素数值。
如果x
的字符是大写的话会发生什么? 如果它是一个数字怎么办? 如果它是一个特殊的角色怎么办? 空间? 标签? 什么不是小写的az字母? 您没有在映射中找到值,它将返回null
。
这也是一个警告 - 在处理盒装基元时,必须非常谨慎 ,当依赖自动装箱转换时,他们不处理任何null
值或实例。 这将导致令人困惑的NPE(像这一样)可能更难跟踪。
我可以想象下面一行的唯一方法就是抛出异常,如果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;
首先,您应该学习如何使用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
,返回值为null
您的数组letters
中没有大写字母,因此地图中没有大写字母!
异常发生在线上
product = product*prodFinder.get(val);
这里jvm试图将地图返回的Integer
到原始int
以执行乘法。 但这是不可能的,因为map返回null
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.