2017-09-20 97 views
1

我正在嘗試編寫一個程序,以便每當按下名爲'front'的按鈕時,除了等於GreenButton的按鈕外,其他所有按鈕都將變爲灰色。我正在努力訪問for循環中的按鈕,並不斷得到空指針異常。從按鈕陣列修改按鈕

完整的logcat如下圖所示,這表明NPE是,當我試圖訪問數組中的循環發生

09-20 11:50:54.727 5302-5302/com.example.kshah.movingbutton E/AndroidRuntime: FATAL EXCEPTION: main 
    Process: com.example.kshah.movingbutton, PID: 5302 
    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.Button.setBackgroundColor(int)' on a null object reference 
     at com.example.kshah.movingbutton.MainActivity$1.onTouch(MainActivity.java:108) 
     at android.view.View.dispatchTouchEvent(View.java:9296) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2553) 
     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2197) 
     at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403) 
     at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737) 
     at android.app.Activity.dispatchTouchEvent(Activity.java:2771) 
     at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69) 
     at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364) 
     at android.view.View.dispatchPointerEvent(View.java:9520) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230) 
     at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
     at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
     at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695) 
     at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661) 
     at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669) 
     at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642) 
     at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5922) 
     at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5896) 
     at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5857) 
     at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:6025) 
     at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185) 
     at android.os.MessageQueue.nativePollOnce(Native Method) 
     at android.os.MessageQueue.next(MessageQueue.java:323) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5417) 
     at java.lang.reflect.Method.invoke(Native Method) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

CODE:

public class MainActivity extends AppCompatActivity { 

    private Button front; 
    private Button a; 
    private Button b1; 
    private Button b2; 
    private Button b3; 
    private Button b4; 

    Button[] buttons = {front,a,b1,b2,b3,b4}; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    front = (Button) findViewById(R.id.front); 
    a = (Button) findViewById(R.id.a); 
    b1 = (Button) findViewById(R.id.b1); 
    b2 = (Button) findViewById(R.id.b2); 
    b3 = (Button) findViewById(R.id.b3); 
    b4 = (Button) findViewById(R.id.b4); 

    front.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent event) { 
       Button GreenButton = b3; 
      for(int i = 0; i <= buttons.length; i++) { 
       if (buttons[i] == b3) { 
        buttons[i].setBackgroundColor(Color.GREEN); 
       } 
       else 
        buttons[i].setBackgroundColor(Color.GRAY); 
      } 
      return false; 
     } 
    }); 
    } 
} 
+0

發佈錯誤的完整logcat。不要修改或修剪 –

+0

使用'for(int i = 0; i

+0

@Pavneet_Singh仍然導致上述錯誤中顯示的空指針異常 –

回答

1

您可以嘗試使用新的按鈕【尺寸】,像這樣:

// allocates memory for 6 button. 
Button[] buttons = new Button[6]; 

然後,添加按鈕將其:

front = (Button) findViewById(R.id.front); 
a = (Button) findViewById(R.id.a); 
b1 = (Button) findViewById(R.id.b1); 
b2 = (Button) findViewById(R.id.b2); 
b3 = (Button) findViewById(R.id.b3); 
b4 = (Button) findViewById(R.id.b4); 

buttons[0] = front; 
buttons[1] = a; 
buttons[2] = b1; 
buttons[3] = b2; 
buttons[4] = b3; 
buttons[5] = b4; 

說明

當你創建陣列:

private Button front; 
private Button a; 
private Button b1; 
private Button b2; 
private Button b3; 
private Button b4; 

Button[] buttons = {front,a,b1,b2,b3,b4}; 

你創建與空對象的數組,這就好比

Button[] buttons = {null,null,null,null,null,null}; 

然後,當你的按鈕分配給數組成員與之一:

front = (Button) findViewById(R.id.front); 

你分配一個對象frontbuttons[0]


你可以試試下面的代碼來理解上述說明的意思:

public class MainActivity extends AppCompatActivity { 
    public static final String TAG = MainActivity.class.getSimpleName(); 

    private Button front; 
    private Button a; 
    private Button b1; 
    private Button b2; 
    private Button b3; 
    private Button b4; 

    Button[] buttons = {front,a,b1,b2,b3,b4}; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // Check address: 
    Log.d(TAG, "Before initializing.."); 
    for(int i = 0; i < buttons.length; i++) { 
     Log.d(TAG, "i " + buttons[i]); 
    } 
    front = (Button) findViewById(R.id.front); 
    a = (Button) findViewById(R.id.a); 
    b1 = (Button) findViewById(R.id.b1); 
    b2 = (Button) findViewById(R.id.b2); 
    b3 = (Button) findViewById(R.id.b3); 
    b4 = (Button) findViewById(R.id.b4); 
    Log.d(TAG, "After initializing.."); 
    for(int i = 0; i < buttons.length; i++) { 
     Log.d(TAG, "i " + buttons[i]); 
    } 

    Log.d(TAG, "After assigning.."); 
    Log.d(TAG, "front " + front); 
    Log.d(TAG, "a " + a); 
    Log.d(TAG, "b1 " + b1); 
    Log.d(TAG, "b2 " + b2); 
    Log.d(TAG, "b3 " + b3); 
    Log.d(TAG, "b4 " + b4); 

    } 
} 
2

不能存儲在引用像這樣的初始化器陣列

Button[] buttons = {front,a,b1,b2,b3,b4}; 

但是爲什麼?放手Array Initializers

數組的長度,以構成等於立即由陣列 初始化的括在大括號 變量初始值設定的數量。空間被分配給這個長度的新數組。如果 沒有足夠的空間來分配數組,則通過拋出OutOfMemoryError突發性地完成對數組初始值設定項的評估。 否則,a one-dimensional array is created of the specified lengthand each component of the array is initialized to its default value

所以這裏的引用將只由值替換意味着null因此他們不能再保持變化的軌跡在實際的參考值

所以解決的辦法是根據要求的長度聲明arrayArrayList並添加對它的引用。

//     {null,null,null,....} 
//Button[] buttons = {front,a,b1,b2,b3,b4}; 
    Button[] buttons = new Button[6]; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    buttons[0] = (Button) findViewById(R.id.front); 
    buttons[1] = (Button) findViewById(R.id.a); 
    buttons[2] = (Button) findViewById(R.id.b1); 
    buttons[3] = (Button) findViewById(R.id.b2); 
    buttons[4] = (Button) findViewById(R.id.b3); 
    buttons[5] = (Button) findViewById(R.id.b4); 

    buttons[0].setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View view, MotionEvent event) { 
       Button GreenButton = b3; 
      // note < instead of <= 
      for(int i = 0; i < buttons.length; i++) { 
       if (buttons[i] == buttons[4]) { 
        buttons[i].setBackgroundColor(Color.GREEN); 
       } 
       else 
        buttons[i].setBackgroundColor(Color.GRAY); 
      } 
      return false; 
     } 
    }); 
0

for(int i = 0; i <= buttons.length; i++){do something with buttons[i]}從來都不是一個有效的「for」循環的原因很簡單。它總是會給你NullPointerException,因爲在循環的最後一個循環中,當我== buttons.length();你正試圖對按鈕[buttons.length()]執行一個簡單不存在的操作。

嘗試for(int i = 0; i < buttons.length; i++){do something with buttons[i]}