zezpwn44
zezpwn44

Reputation: 9

(Java) Code works when using subclass, but using superclass causes a null pointer error?

I am writing a program to play spades.

I have a class, GenericSpadesPlayer

and two subclasses

SpadesPlayer extends GenericSpadesPlayer (these are computer players.), and HumanSpadesPlayer extends GenericSpadesPlayer

The GenericSpadesPlayerClass, in its entirety, is as follows:

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

    public abstract class GenericSpadesPlayer{

      Set<Card> hand;
      int playerKey;

  public abstract Card playCard(Card[] playedCards, int[] bids, int[] tricksTaken, int leadSuit);
  public abstract int getBid();

}

Each of these member variables and methods are implemented in the SpadesPlayer and HumanSpadesPlayer classes, and both classes compile without errors.

The problem is in the main method of the class that runs the game. Originally, I had only created SpadesPlayer objects, and my code read:

SpadesPlayer north = new SpadesPlayer(3);
SpadesPlayer south = new SpadesPlayer(1);
SpadesPlayer east = new SpadesPlayer(4);
SpadesPlayer west = new SpadesPlayer(2);

SpadesPlayer[] rotation = {south, west, north, east};

and then, when I dealt the cards:

for (int i=0; i<deck.deck.length; i++){
  rotation[currentPos].hand.add(deck.dealCard()); //currentPos is initialized to be 1
  currentPos = (currentPos + 1) % 4;
}

Everything works fine.

The problem came when I developed the GenericSpadesPlayer class and allowed SpadesPlayer and HumanSpadesPlayer to inherit from it. When I changed:

SpadesPlayer[] rotation = {south, west, north, east};

to

GenericSpadesPlayer[] rotation = {south, west, north, east};

, I got an error on the following line:

rotation[currentPos].hand.add(deck.dealCard());

After attempting to debug, the program says that rotation[currentPos].hand is null. Hand is not initialized in GenericSpadesPlayer because it is an abstract class; however, south, west, north, and east (all the elements of the rotation array) are all SpadesPlayers or HumanSpadesPlayers, and hand is initialized in their constructors. It should also be noted that no matter what combination of SpadesPlayers or HumanSpadesPlayers I include in the rotation array, I always get this error, as long as rotation is declared to be an array of GenericSpadesPlayers and not SpadesPlayers.

Any advice? I thought making an array of GenericSpadesPlayers would allow me to populate it with both SpadesPlayers and HumanSpadesPlayers, but I appear to be running into issues.

Upvotes: 0

Views: 606

Answers (1)

Eric Guan
Eric Guan

Reputation: 15982

Each of these member variables and methods are implemented in the SpadesPlayer and HumanSpadesPlayer classes, and both classes compile without errors.

I suspect this is the issue. If you redeclared Set<Card> hand in your subclasses, it will overwrite the Set<Card> hand in your superclass. Then once you switch your array from the subclass to the superclass, you're gonna get a null point exception.

You don't need to redeclare Set<Card> hand in your subclasses, you can already access them freely. When you inherit from a class, you have access to all of it's variables and methods. You just can't literally see them in your subclass code.

Here's a simple example.

Super class with a List, not initialized. If i try to use this variable i will get a null pointer exception.

public class mySuper {

    public static List<Integer> test;

}

Subclass which inherits from the above class. I redeclared the variable, which is what i think you did. I also initialized it, so if i try to use this variable i will NOT get a null pointer exception.

public class mySub extends mySuper{

    public static List<Integer> test = new ArrayList<Integer>();

}

Main method, analogous to yours.

public static void main(String[] args){
        mySub[] mySubArray = {new mySub()};
        System.out.println(mySubArray[0].test.size()); //prints 0

        mySuper[] mySuperArray = {new mySub()}; 
        System.out.println(mySuperArray[0].test.size()); //null pointer exception
    }

How to fix this.

Properly initialize the variable in the superclass.

public class mySuper {

    public static List<Integer> test  = new ArrayList<Integer>();

}

Take out the declaration in your subclass, you can still use it.

public class mySub extends mySuper{


}

public static void main(String[] args){
        mySub[] mySubArray = {new mySub()};
        System.out.println(mySubArray[0].test.size()); //prints 0

        mySuper[] mySuperArray = {new mySub()}; 
        System.out.println(mySuperArray [0].test.size()); //prints 0
    }

You can reassign the variable in your subclass. However you if redeclare it, that's when it overwrites the superclass variable.

Upvotes: 1

Related Questions