我正在编写一个玩黑桃的程序。
我有一个类,GenericSpadesPlayer
和两个子类
SpadesPlayer 扩展了 GenericSpadesPlayer(这些是计算机播放器。),并且 HumanSpadesPlayer 扩展了 GenericSpadesPlayer
GenericSpadesPlayerClass 的整体结构如下:
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();
}
每个成员变量和方法都在 SpadesPlayer 和 HumanSpadesPlayer 类中实现,并且这两个类编译时都没有错误。
问题出在运行游戏的类的 main 方法中。最初,我只创建了 SpadesPlayer 对象,我的代码如下:
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};
然后,当我发牌时:
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;
}
一切正常。
当我开发 GenericSpadesPlayer 类并允许 SpadesPlayer 和 HumanSpadesPlayer 继承它时,问题就出现了。当我改变时:
SpadesPlayer[] rotation = {south, west, north, east};
至
GenericSpadesPlayer[] rotation = {south, west, north, east};
,我在以下行中遇到错误:
rotation[currentPos].hand.add(deck.dealCard());
尝试调试后,程序显示rotation[currentPos].hand 为空。 Hand 在 GenericSpadesPlayer 中没有初始化,因为它是一个抽象类;然而,south、west、north 和 east(旋转数组的所有元素)都是 SpadesPlayers 或 HumanSpadesPlayers,并且 hand 在它们的构造函数中初始化。还应该注意的是,无论我在旋转数组中包含 SpadesPlayers 或 HumanSpadesPlayers 的哪种组合,只要将旋转声明为 GenericSpadesPlayers 而不是 SpadesPlayers 的数组,我总是会收到此错误。
有什么建议吗?我认为制作一个 GenericSpadesPlayers 数组可以让我用 SpadesPlayers 和 HumanSpadesPlayers 填充它,但我似乎遇到了问题。
最佳答案
Each of these member variables and methods are implemented in the SpadesPlayer and HumanSpadesPlayer classes, and both classes compile without errors.
我怀疑这就是问题所在。如果您重新声明Set<Card> hand
在您的子类中,它将覆盖 Set<Card> hand
在你的父类(super class)中。然后,一旦将数组从子类切换到父类(super class),您将得到一个空点异常。
您不需要重新声明Set<Card> hand
在您的子类中,您已经可以自由访问它们。当您从类继承时,您可以访问它的所有变量和方法。您只是无法在子类代码中真正看到它们。
这是一个简单的示例。
super 类 List
,未初始化。如果我尝试使用这个变量,我将得到一个空指针异常。
public class mySuper {
public static List<Integer> test;
}
继承自上述类的子类。我重新声明了变量,我认为这就是你所做的。我还初始化了它,所以如果我尝试使用这个变量,我将不会得到空指针异常。
public class mySub extends mySuper{
public static List<Integer> test = new ArrayList<Integer>();
}
主要方法,与您的类似。
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
}
<小时/>
如何解决这个问题。
正确初始化父类(super class)中的变量。
public class mySuper {
public static List<Integer> test = new ArrayList<Integer>();
}
把子类中的声明去掉,仍然可以使用。
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
}
您可以重新分配子类中的变量。但是,如果您重新声明它,那么它就会覆盖父类(super class)变量。
关于java - (Java) 使用子类时代码可以工作,但使用父类(super class)会导致空指针错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33313083/