Android NullPointerException 导致崩溃

Posted

技术标签:

【中文标题】Android NullPointerException 导致崩溃【英文标题】:Android NullPointerException causing crash 【发布时间】:2012-05-03 22:14:13 【问题描述】:

我正在创建一个安卓纸牌游戏。我创建了一个扑克牌类和一个纸牌类。当我运行示例代码时,它无法构建甲板。这是我的代码以及 logcat

PlayingCard.java

package com.michaelpeerman.hi_low;

public class PlayingCard 
public String[] CardSuit = "SPADE","HEART","CLUB","DIAMOND";
public String[] CardRank= "ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE","JACK","QUEEN","KING";
public String theSuit;
public int theRank;
public boolean theState;

public PlayingCard()
    theSuit = "SPADE";
    theRank = 1;
    theState = false;

public PlayingCard(String mySuit, int myRank)
    theSuit = mySuit;
    theRank = myRank;


public int getRank()
    return theRank;


public String getSuit()
    return theSuit;


public boolean getState()
    return theState;


public void setState(boolean myState)
    theState = myState;

public void setRank(int myRank)
    theRank = myRank;

public void setSuit(String mySuit)
    theSuit = mySuit;

public String getCardString()
     String cardString = null;
        String theCardRanks[] = "A","2","3","4","5","6","7","8","9","T","J","Q","K";

        if (theSuit == "CLUB")
            cardString = "C"+theCardRanks[theRank-1];
        else if (theSuit == "SPADE")
            cardString = "S"+theCardRanks[theRank-1];
        else if (theSuit == "HEART")
            cardString = "H"+theCardRanks[theRank-1];
        else if (theSuit == "DIAMOND")
            cardString = "D"+theCardRanks[theRank-1];
        return cardString;


CardDeck.java

package com.michaelpeerman.hi_low;
import java.util.Random;

import com.michaelpeerman.hi_low.PlayingCard;
public class CardDeck 
public PlayingCard[] cardArray;
public int num_decks;
public int cards_left;
public CardDeck(int my_decks)

num_decks = my_decks;
cardArray = new PlayingCard[52*num_decks];
cards_left = 52*num_decks;
for (int i=0; i< num_decks; i++)
for (int j = 0; j < 13; j++)


        cardArray[(j+(52*i))].setSuit("SPADE");
        cardArray[j+13+(52*i)].setSuit("HEART");
        cardArray[j+26+(52*i)].setSuit("CLUB");
        cardArray[j+39+(52*i)].setSuit("DIAMOND");




    if (j==0)
        cardArray[j+(52*i)].setRank(1);
        cardArray[j+13+(52*i)].setRank(1);
        cardArray[j+26+(52*i)].setRank(1);
        cardArray[j+39+(52*i)].setRank(1);
        
    else if (j==1)
        cardArray[j+(52*i)].setRank(2);
        cardArray[j+13+(52*i)].setRank(2);
        cardArray[j+26+(52*i)].setRank(2);
        cardArray[j+39+(52*i)].setRank(2);
        
    else if (j==2)
        cardArray[j+(52*i)].setRank(3);
        cardArray[j+13+(52*i)].setRank(3);
        cardArray[j+26+(52*i)].setRank(3);
        cardArray[j+39+(52*i)].setRank(3);
        
    else if (j==3)
        cardArray[j+(52*i)].setRank(4);
        cardArray[j+13+(52*i)].setRank(4);
        cardArray[j+26+(52*i)].setRank(4);
        cardArray[j+39+(52*i)].setRank(4);
        
    else if (j==4)
        cardArray[j+(52*i)].setRank(5);
        cardArray[j+13+(52*i)].setRank(5);
        cardArray[j+26+(52*i)].setRank(5);
        cardArray[j+39+(52*i)].setRank(5);
        
    else if (j==5)
        cardArray[j+(52*i)].setRank(6);
        cardArray[j+13+(52*i)].setRank(6);
        cardArray[j+26+(52*i)].setRank(6);
        cardArray[j+39+(52*i)].setRank(6);
        
    else if (j==6)
        cardArray[j+(52*i)].setRank(7);
        cardArray[j+13+(52*i)].setRank(7);
        cardArray[j+26+(52*i)].setRank(7);
        cardArray[j+39+(52*i)].setRank(7);
        
    else if (j==7)
        cardArray[j+(52*i)].setRank(8);
        cardArray[j+13+(52*i)].setRank(8);
        cardArray[j+26+(52*i)].setRank(8);
        cardArray[j+39+(52*i)].setRank(8);
        
    else if (j==8)
        cardArray[j+(52*i)].setRank(9);
        cardArray[j+13+(52*i)].setRank(9);
        cardArray[j+26+(52*i)].setRank(9);
        cardArray[j+39+(52*i)].setRank(9);
        
    else if (j==9)
        cardArray[j+(52*i)].setRank(10);
        cardArray[j+13+(52*i)].setRank(10);
        cardArray[j+26+(52*i)].setRank(10);
        cardArray[j+39+(52*i)].setRank(10);
        
    else if (j==10)
        cardArray[j+(52*i)].setRank(11);
        cardArray[j+13+(52*i)].setRank(11);
        cardArray[j+26+(52*i)].setRank(11);
        cardArray[j+39+(52*i)].setRank(11);
        
    else if (j==11)
        cardArray[j+(52*i)].setRank(12);
        cardArray[j+13+(52*i)].setRank(12);
        cardArray[j+26+(52*i)].setRank(12);
        cardArray[j+39+(52*i)].setRank(12);
        
    else if (j==12)
        cardArray[j+(52*i)].setRank(13);
        cardArray[j+13+(52*i)].setRank(13);
        cardArray[j+26+(52*i)].setRank(13);
        cardArray[j+39+(52*i)].setRank(13);
        




public void useCard()
cards_left = cards_left - 1;

public int get_cards_left()
return cards_left;

public void setCard(int card, PlayingCard myCard)
cardArray[card]=myCard;



public PlayingCard getCard(int card)

return cardArray[card];



public void printDeck()
for (int j = 0; j < (52*num_decks); j++)
    // Print out to textview
    //String cardString = cardArray[j].getCardString();



public void suffleDeck()

for (int i = 0; i < 100*num_decks; i++)

    int rand1 = 1 + new Random().nextInt(52*num_decks);
    int rand2 = 1 + new Random().nextInt(52*num_decks);
    PlayingCard tmpCard = cardArray[rand1];
    cardArray[rand1] = cardArray[rand2];
    cardArray[rand2] = tmpCard;


public boolean isDeckFinished()
boolean isFinished =true;
for (int i = 0; i<52*num_decks; i++)
    PlayingCard myCard = cardArray[i];
    if (myCard.getState() == false)
        isFinished = false;
    

return isFinished;




StartScreen.java

package com.michaelpeerman.hi_low;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import com.michaelpeerman.hi_low.R;
import com.michaelpeerman.hi_low.CardDeck;
import com.michaelpeerman.hi_low.PlayingCard;

public class StartScreen extends Activity 
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    CardDeck myDeck = new CardDeck(1);
    int cards = myDeck.cards_left;
    String text = Integer.toString(cards);
   TextView t=new TextView(this); 

    t=(TextView)findViewById(R.id.main_text); 
    t.append(text);



main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_
android:layout_ >
<ScrollView
android:layout_
android:layout_>
<TextView
    android:id="@+id/main_text"
    android:layout_
    android:layout_
     />
</ScrollView>
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.michaelpeerman.hi_low"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk android:minSdkVersion="13" />

<application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name" >
    <activity
        android:name=".StartScreen"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

</manifest>

LogCat 输出

05-03 18:03:55.067: E/AndroidRuntime(9805): FATAL EXCEPTION: main
05-03 18:03:55.067: E/AndroidRuntime(9805): java.lang.RuntimeException: Unable to start activity ComponentInfocom.michaelpeerman.hi_low/com.michaelpeerman.hi_low.StartScreen: java.lang.NullPointerException
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread.access$600(ActivityThread.java:123)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.os.Looper.loop(Looper.java:137)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread.main(ActivityThread.java:4424)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at java.lang.reflect.Method.invokeNative(Native Method)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at java.lang.reflect.Method.invoke(Method.java:511)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at dalvik.system.NativeStart.main(Native Method)
05-03 18:03:55.067: E/AndroidRuntime(9805): Caused by: java.lang.NullPointerException
05-03 18:03:55.067: E/AndroidRuntime(9805):     at com.michaelpeerman.hi_low.CardDeck.<init>(CardDeck.java:18)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at com.michaelpeerman.hi_low.StartScreen.onCreate(StartScreen.java:16)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.Activity.performCreate(Activity.java:4465)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
05-03 18:03:55.067: E/AndroidRuntime(9805):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
05-03 18:03:55.067: E/AndroidRuntime(9805):     ... 11 more

【问题讨论】:

【参考方案1】:

您正在正确地创建cardArray,但您没有使用对PlayingCard 的任何引用来填充它。在您将它们设置为某个值之前,它们都是空值。

【讨论】:

我想用 cardArray = new PlayingCard[52*num_decks];在 CardDeck 类的构造函数中是这样做的吗? 所以我需要运行 cardArray[j] = new PlayingCard;对吗? 没有。它只是为52*num_decks 的引用量创建和分配内存。在您明确创建对象之前,不会创建对象。 for(int k = 0; k &lt; cardArray.length; i++)cardArray[k] = new PlayingCard(); 会这样做。 嗯,看来我的回答为时已晚 :) 但是不,您所做的只是定义一个包含 PlayingCard 对象且当前为空的数组。您需要自己实例化和添加对象。 在一个不相关的注释上,也许你可以在你的 public CardDeck(int my_decks) 函数中做这样的事情:cardArray[j+(52*i)].setRank(j+1); 而不是做这个巨大的 if/else 事情......会更具可读性。 【参考方案2】:

根据堆栈跟踪,有问题的行是:

cardArray[(j+(52*i))].setSuit("SPADE");

在 CardDeck.java 中。

我猜这是因为该数组元素的内容为空。虽然您已经定义了数组,但在尝试对其元素调用 .setSuit(...) 之前似乎没有将任何对象放入其中 - 所以您在 null 上调用 .setSuit(...)因此是 NPE。

【讨论】:

用 PlayingCard 类型的对象填充数组的最简单方法是什么? 请原谅我最初用 C++ 编写了这个程序并试图将其转换为 android 不用担心。最简单的方法就是循环添加 PlayingCard 对象。您可以这样做:(为缺少格式而道歉) for(int i=0; i

以上是关于Android NullPointerException 导致崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Android 中处理 NullPointerException?

<WebLogicServer; <BEA-000386; <Server subsystem failed. Reason: java.lang.NullPointerExcept

Maven打包时出现“Show Console View”错误弹出框,错误详情为“An internal error has occurred. java.lang.NullPointerExcept

Maven打包时出现“Show Console View”错误弹出框,错误详情为“An internal error has occurred. java.lang.NullPointerExcept

Android proguard 混淆代码实际上不应该导致 NullPointerException

RecyclerView的坑