0

我仔细阅读了许多其他 NPE 解决方案,并且我尝试实施其他建议,但没有一个完全符合我正在尝试做的事情,它只会导致更多的 eclipse 错误。我已经编译并尝试从命令行运行,在命令行运行时为我正在运行的应用程序提供了几个字符串。下面是主类,以及包含主使用的方法的类。

使用 main 方法的类:

package my.package.ext;



public class WordCounterApp {

    /**
     * @param args
     * Two command line arguments: the first one needs to be in quotes, the string that will be used, the second optional argument
     * is the unique word to be counted (countWord method).
     * @param source 
     * @param word 
     */
    public static void main(String[] args) {
        String source = null;
        String uniqueword = null;
        StringBuilder word = null;
        WordCounter counter = new WordCounter(source, word);
        WordCounter uniqueCounter = new WordCounter(source, uniqueword);
        counter.countWords(source);
        counter.countUniqueWords(source);
        uniqueCounter.countWord(source, uniqueword);

}

}

使用其他方法进行类:

package my.package.ext;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.lang.Character;
import java.lang.StringBuilder;

public class WordCounter {
    public Integer counter = 0;
    public String source;
    public HashSet<String> hashset;
    public StringBuilder word;
    public String uniqueword;

    public WordCounter(String source) {
         counter = new Integer(counter);
    }
    public WordCounter(String source, StringBuilder word) {
         counter = new Integer(counter);
    }
    public WordCounter(String source, String uniqueword) {
        counter = new Integer(counter);
    }
    /**
     *  
     * @param line - the string parameter to get a total word count from.
     */

    public int countWords(String source) {

        boolean word = false;
        int endOfLine = source.length() - 1;
        Integer counter = 0;

        for (int i = 0; i < source.length(); i++) {
            if (Character.isLetter(source.charAt(i)) == true && i != endOfLine) {
                word = true;
            //} else if (Character.charValue(line.charAt(i)) == "-" && i != endOfLine) {
            //  word = true;
            } else if (Character.isLetter(source.charAt(i)) == false && word == true) {
                counter++;
                word = false;
            } else if (Character.isLetter(source.charAt(i)) && i == endOfLine) {
                counter++;
            }
        }
        System.out.println(counter);
        return counter;
    }




/**
 * 
 * @param line - the string parameter that we will return the unique word count from. Randy recommends a HashSet.
 * Put it into a hashset. Hashsets don't allow duplicate elements. Then do a count. 
 */

    public int countUniqueWords(String line) {
        hashset = new HashSet<String>();
        word = new StringBuilder();
        int endOfLine = line.length() - 1;
        boolean isWord = false;
        String stringWord = null;
        Integer counter = 0;

        for (int i = 0; i < line.length(); i++) {
            if (Character.isLetter(line.charAt(i)) == true && i != endOfLine) {
                //System.out.println(i);
                word.append(line.charAt(i));
                isWord = true;
            } else if (Character.isLetter(line.charAt(i)) == false && isWord == true) {
                counter++;
                //System.out.println("Counter is: " + counter);
                stringWord = word.toString();
                //System.out.println("stringWord is now: " + stringWord);
                hashset.add(stringWord);
                //System.out.println(hashset);
                word = new StringBuilder();
                isWord = false;
            } else if (Character.isLetter(line.charAt(i)) && i == endOfLine) {
                counter++;
                stringWord = word.toString();
                hashset.add(stringWord);
            }
        }
        //System.out.println(counter);
        System.out.println("There are " + hashset.size() + " unique words in this string");
        System.out.println("These are the unique words in the string: " + hashset);
        return counter;

    }


/**
 * 
 * @param source - the string the word is to be counted from
 * @param word - the word to be counted
 * 
 */
    public void countWord(String source, String word) {

        String str = source;
        Pattern p = Pattern.compile("\\s"+word+"\\s");
        Matcher m = p.matcher(str);
        int count = 0;
        while (m.find()) {
            count++;
        }
        System.out.println("The word: " + "\"" + word + "\"" + " appears " + count + " times.");
        }

}

我在这里确定了 NPE 的来源:

public int countWords(String source) {

    boolean word = false;
    int endOfLine = source.length() - 1;  //the source of the NPE is this line
    Integer counter = 0;

所以看着那个,我想我没有正确初始化源。我尝试过类似 WordCounter source = new WordCounter()

但是我尝试的每一个变体,引入正确的构造函数,都会给我其他 eclipse 错误。我似乎无法到达那里,我担心我走错了路。我可能在这里也有其他问题。我也不确定从命令行运行的正确方法,同时将一些字符串作为参数传递给方法。提前致谢

4

7 回答 7

2

source的主要方法中的字符串是null,并且您将其作为参数传递给countWords方法。

 public static void main(String[] args) {
        String source = null;// it is null here
        ..............
        ............
        counter.countWords(source);// passing null here

因此,当您打电话时,在您的 countWords 中

    int endOfLine = source.length() - 1;

由于您的来源为空,它将抛出 NullPointerException。

初始化您的字符串以摆脱 NPE。

编辑:如果你想将 source 作为命令行参数传递。

String source =args[0];

并在运行时传递命令行参数。

于 2012-11-05T23:31:02.887 回答
0

你的主要方法:

public static void main(String[] args) {
        String source = null;
        // ... a few lines
        counter.countWords(source);
        // ... more code

}

产生的错误:

public int countWords(String source) {
    boolean word = false;
    int endOfLine = source.length() - 1;  //the source of the NPE is this line
    Integer counter = 0;
}

发生是source因为null.

于 2012-11-05T23:30:59.203 回答
0

您将 null 作为源传递并稍后调用 source.length 。这会导致 NPE。

于 2012-11-05T23:31:25.083 回答
0

counter.countWords(source);

这里源字符串为空,导致 NPE。

于 2012-11-05T23:31:47.710 回答
0

在您的主要方法中,您分配source为 be null。你永远不会将它重新分配给其他任何东西,所以当你调用counter.countWords(source)它时,它相当于调用counter.countWords(null)

这意味着,当您到达countWords()它尝试调用的行时source.length()source实际上会null导致 aNullPointerException被抛出。为避免这种情况,您必须source在调用该方法之前将其赋值为某物。

于 2012-11-05T23:32:58.517 回答
0

这是我的版本,基于您的“手动行解析”方法:

package forums;

import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.HashSet;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class WordCounterApp {

    private static void printUsage() {
        System.out.println("usage: java -cp C:\\Java\\home\\classes forums.WordCounterApp <text> [targetWord]");
        System.out.println("   <text> is a quoted string to be split into words.");
        System.out.println("   optional [targetWord] to be counted seperately.");
    }

    /**
     * @param args
     *  REQUIRED [0] text: a quoted string to be searched for words. 
     *  OPTIONAL [1] targetWord: the word to be counted, if desired.
     */
    public static void main(String[] args) {
        if (args.length==0) {
            printUsage();
            return;
        }
        String text = args[0];
        String targetWord = args.length>1 ? args[1] : null;
        WordCount wordCount = new WordCount(text);

        System.out.println();

        // all words in this string
        List<String> words = wordCount.all();
        System.out.println("There are "+words.size()+" words in the string. That are:\n"+words);
        System.out.println();

        // unique words in this string
        Set<String> uniqueWords = wordCount.unique();
        System.out.println("There are "+uniqueWords.size()+" unique words in the string. They are:\n"+uniqueWords);
        System.out.println();

        // the number of occurrences of the target word in this string, if given
        if (targetWord ! = null) {
            int targetCount = wordCount.of(targetWord);
            System.out.println("The word \""+targetWord+"\" appears "+targetCount+" times.");
            System.out.println();
        }

    }
}

/**
 * Counts the words on a line, in various ways.
 */
class WordCount 
{
    private final String _line;
    public WordCount(String line) {
        _line = line;
    }

    public List<String> all() {
        final List<String> results = new ArrayList<String>(64); // just a guess at max word-count.
        final Matcher matcher = Pattern.compile("\\w+").matcher(_line);
        int count = 0;
        while ( matcher.find() )
            results.add(matcher.group());
        return results;
    }

    /**
     * Returns a set of the unique words in the line
     */
    public Set<String> unique() {
        final HashSet<String> results = new HashSet<String>();
        final int lineLength = _line.length();
        final int endOfLine = lineLength-1;
        final StringBuilder wordBuffer = new StringBuilder(16); // just a guess at max-word-length
        char ch;
        boolean isInWord = false;
        // foreach character in the line EXCEPT the last one:
        for ( int i=0; i<endOfLine; ++i ) {
            ch = _line.charAt(i);
            if ( Character.isLetter(ch) ) {
                // we're at the start or continuation of the current word.
                wordBuffer.append(ch);
                isInWord = true;
            } else if ( isInWord ) {
                // we're reached the end-of-word, or the end-of-the-line.
                results.add(wordBuffer.toString());
                wordBuffer.setLength(0); // clear the word-buffer.
                isInWord = false;
            }
        }
        // handle the last character in the line seperately, just to save
        // testing for it everytime through the loop... and I personally 
        // think that the logic is easier to follow this way.
        ch = _line.charAt(endOfLine);
        if ( Character.isLetter(ch) )
            wordBuffer.append(ch);
        if ( wordBuffer.length() > 0 )
            results.add(wordBuffer.toString());
        return results;
    }

    /**
     * Returns the number of occurences of the targetWord.
     * @param targetWord - the word to be counted.
     */
    public int of(String targetWord) {
        final String regex = "\\s+"+targetWord+"\\s+";
        final Matcher matcher = Pattern.compile(regex).matcher(_line);
        int count = 0;
        while ( matcher.find() )
            ++count;
        return count;
    }

}

如果是为自己做这个,该all方法将只使用String.split(String regex)(因为它更简洁);然后该unique方法将从该方法的结果开始all,而不是“手动解析”这些单词(再次因为它更简洁)。

Also, if I was doing this for real I'd be inclined to have one frequencyTable method that returns a HashMap<String, int> containing "the frequency table" - i.e. a map of each distinct word to the number of times it occurs. This recipe is flexible (and therefore reusable) and tends to be more efficient because you typically parse a line once, and then repeatedly query the parse-results... and if you're only querying the result once then you really haven't lost anything except a few clockticks, and they come in billions these days.

于 2012-11-06T01:25:39.463 回答
-1

城市 17 大亨,

我停止阅读您的 main 方法,因为我已经找到了一个显示停止器:您根本没有做任何事情args(传递给 main 方法的命令行参数)......所以您的source,uniqueWordwordvariables 都是 ALLWAYS null。 ..我认为这是你的根本原因NullPointerException

您可能还想在谷歌上搜索:如何阅读堆栈跟踪......这是新程序员必须学习的技能,并且该技能甚至可以在(几乎所有)现代语言之间移植。

堆栈跟踪会准确地告诉您 NPE 发生在哪一行代码上,并且从那里通常很容易确定哪些变量是空的……特别是如果您使用调试器……只需放一个断点在违规行上,使用相同的输入重新运行程序,并检查该行上所有变量的值......其中一个或多个必须为空。

干杯。基思。

于 2012-11-05T23:37:04.480 回答