为什么会发生这些nullPointerException

时间:2014-12-11 21:57:29

标签: java nullpointerexception

我已经阅读过有关空指针异常的帖子,但仍无法解决我的问题。

这是我为扑克游戏写的playCard课程。我有Card类和Deck类。

class Card {

    /* constant suits and ranks */
    static final String[] Suit = {"Clubs", "Diamonds", "Hearts", "Spades"};
    static final String[] Rank = {"", "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

    /* Data field of a card: rank and suit */
    private int cardRank;  /* values: 1-13 (see Rank[] above) */
    private int cardSuit;  /* values: 0-3  (see Suit[] above) */

    /* Constructor to create a card */
    /* throw MyPlayingCardException if rank or suit is invalid */
    public Card(int rank, int suit) throws MyPlayingCardException {
        if ((rank < 1) || (rank > 13))
            throw new MyPlayingCardException("Invalid rank:" + rank);
        else
            cardRank = rank;
        if ((suit < 0) || (suit > 3))
            throw new MyPlayingCardException("Invalid suit:" + suit);
        else
            cardSuit = suit;
    }

    /* Accessor and toString */
    /* You may impelemnt equals(), but it will not be used */
    public int getRank() {
        return cardRank;
    }

    public int getSuit() {
        return cardSuit;
    }

    public String toString() {
        return Rank[cardRank] + " " + Suit[cardSuit];
    }

    /* Few quick tests here */
    public static void main(String args[]) {
        try {
            Card c1 = new Card(1, 3);    // A Spades
            System.out.println(c1);
            c1 = new Card(10, 0);    // 10 Clubs
            System.out.println(c1);
            c1 = new Card(10, 5);        // generate exception here
        } catch (MyPlayingCardException e) {
            System.out.println("MyPlayingCardException: " + e.getMessage());
        }
    }
}

class Decks {

    /* this is used to keep track of original n*52 cards */
    private List<Card> originalDecks;

    /* this starts with n*52 cards deck from original deck   */
    /* it is used to keep track of remaining cards to deal */
    /* see reset(): it resets dealDecks to a full deck      */
    private List<Card> dealDecks;

    /* number of decks in this object */
    private int numberDecks;

    /**
     * Constructor: Creates default one deck of 52 playing cards in originalDecks and
     * copy them to dealDecks.
     * initialize numberDecks=n
     * Note: You need to catch MyPlayingCardException from Card constructor
     * Use ArrayList for both originalDecks & dealDecks
     */
    public Decks() {
        // implement this method!

        ArrayList<Card> originalDecks = new ArrayList<Card>(52);
        ArrayList<Card> dealDecks = new ArrayList<Card>(52);

        Card card;

        for (int i = 0; i <= 3; i++) {

            for (int j = 1; j <= 13; j++) {

                try {
                    card = new Card(j, i);

                    if (card != null) {
                        **originalDecks.add(card);**
                    }
                } catch (MyPlayingCardException e) {

                    System.out.println("MyPlayingCardException: " + e.getMessage());

                }

            }  //end of 1st for loop
        }      //end of 2nd for loop

        dealDecks.addAll(originalDecks);
    }

    /**
     * Constructor: Creates n decks (52 cards each deck) of playing cards in
     * originalDecks and copy them to dealDecks.
     * initialize numberDecks=n
     * Note: You need to catch MyPlayingCardException from Card constructor
     * Use ArrayList for both originalDecks & dealDecks
     */
    public Decks(int n) {
        int numberDecks = n;
        Card card;

        for (int m = 0; m < n; m++) {

            for (int i = 0; i <= 3; i++) {

                for (int j = 0; j <= 13; j++) {

                    try {
                        card = new Card(j, i);
                        if (card != null) {
                            **originalDecks.add(card);**
                        }
                    } catch (MyPlayingCardException e) {
                        System.out.println("MyPlayingCardException: " + e.getMessage());
                    }

                }
            }
        }

        dealDecks.addAll(originalDecks);
    }
}

空指针异常发生在strong的行中,即card = new Card(j,i)。我读了这篇文章,认为我的问题是&#34; card = null&#34; case,所以我添加了&#34; if(card!= null)&#34;,但它没有解决问题。这里出了什么问题?

1 个答案:

答案 0 :(得分:1)

您有两个Decks构造函数,它们有两个不同的问题:

Decks()构造函数(无参数):

Deck()构造函数中的这一行会创建一个本地变量,用于隐藏(隐藏)您的实例成员:

ArrayList<Card> originalDecks = new ArrayList<Card>(52);

这意味着您永远不会初始化您的实例成员,因此它会保留其默认值(null)。如果您尝试对实例成员执行任何操作(例如,在该构造函数之外),则会因NPE而失败,因为您从未向实例成员分配任何内容。

您在该构造函数中突出显示的行不会抛出,因为它使用局部变量,而不是实例成员。

要初始化实例成员而不是在构造函数中声明和初始化局部变量,请删除返回类型,这样您就不会声明变量,而只是分配给您的实例成员:

originalDecks = new ArrayList<Card>(52);

dealDecks存在同样的问题。

Decks(int)构造函数:

这个更简单:您永远不会分配给originalDecks,因此它会保留其null值,并且您突出显示的行会抛出。如果没有,则会在dealDecks.add行之后抛出,因为您从未向dealDecks分配任何内容。


这一位是主观的

第一个问题是我建议在引用实例成员时始终使用this.的原因之一:

this.originalDecks = new ArrayList<Card>(52);

那样的方式A)很明显你正在处理实例成员而不是局部变量,而且B)所以你不能犯这个错误(因为ArrayList<Card> this.originalDecks = ...会出现语法错误)。某些IDE和lint工具甚至有一个选项,您可以启用此选项,以便在实例mebers上不使用this.错误或警告。