安卓报错:Attempt to invoke virtual method

不知道为啥,一按按钮,软件就闪退。求援助。

这个是报错日志

 E  FATAL EXCEPTION: main
                                                                                                    Process: com.example.exercise2_4, PID: 10924
                                                                                                    java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
                                                                                                        at com.example.exercise2_4.MainActivity.refreshText(MainActivity.java:105)
                                                                                                        at com.example.exercise2_4.MainActivity.onClick(MainActivity.java:78)
                                                                                                        at android.view.View.performClick(View.java:7441)
                                                                                                        at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1131)
                                                                                                        at android.view.View.performClickInternal(View.java:7418)
                                                                                                        at android.view.View.access$3700(View.java:835)
                                                                                                        at android.view.View$PerformClick.run(View.java:28676)
                                                                                                        at android.os.Handler.handleCallback(Handler.java:938)
                                                                                                        at android.os.Handler.dispatchMessage(Handler.java:99)
                                                                                                        at android.os.Looper.loopOnce(Looper.java:201)
                                                                                                        at android.os.Looper.loop(Looper.java:288)
                                                                                                        at android.app.ActivityThread.main(ActivityThread.java:7839)
                                                                                                        at java.lang.reflect.Method.invoke(Native Method)
                                                                                                        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
                                                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

这个是java源代码 报错处我已经加粗

package com.example.exercise2_4;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private  TextView txt;
    private  String firstNum = "";
    private  String operator = "";
    private  String secondNum = "";
    private  String result = "";
    private  String showText = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView txt =findViewById(R.id.tv01);
        findViewById(R.id.btn_cancel).setOnClickListener(this);
        findViewById(R.id.one).setOnClickListener(this);
        findViewById(R.id.two).setOnClickListener(this);
        findViewById(R.id.three).setOnClickListener(this);
        findViewById(R.id.four).setOnClickListener(this);
        findViewById(R.id.five).setOnClickListener(this);
        findViewById(R.id.six).setOnClickListener(this);
        findViewById(R.id.seven).setOnClickListener(this);
        findViewById(R.id.eight).setOnClickListener(this);
        findViewById(R.id.nine).setOnClickListener(this);
        findViewById(R.id.zero).setOnClickListener(this);
        findViewById(R.id.add).setOnClickListener(this);
        findViewById(R.id.minus).setOnClickListener(this);
        findViewById(R.id.multiply).setOnClickListener(this);
        findViewById(R.id.chuyu).setOnClickListener(this);
        findViewById(R.id.denyu).setOnClickListener(this);
        findViewById(R.id.point).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        String inPutText;
        inPutText = ((TextView)v).getText().toString();
        switch(v.getId()){
            case R.id.btn_cancel:
                clear();
                break;
            case R.id.add:
            case R.id.minus:
            case R.id.multiply:
            case R.id.chuyu:
                operator =  inPutText;
                refreshText(showText + operator);
                break;

            case R.id.denyu:
                double calculate_result =calculateFour();
                refreashOperate(String.valueOf(calculate_result));
                refreshText(showText + "=" + result);
                break;

            default:
                if(result.length() > 0 && operator.equals("")){
                    clear();
                }

                if(operator.equals("")){
                    firstNum = firstNum + inPutText;
                }else{
                secondNum = secondNum +inPutText;
            }
            if(showText.equals("0") && !inPutText.equals(".")) {
                refreshText(inPutText);
            }else{
               ** refreshText(showText + inPutText);**
            }
        }

    }

    private double calculateFour() {
        switch(operator){
            case "+":
                return Double.parseDouble(firstNum) + Double.parseDouble(secondNum);

            case "-":
                return Double.parseDouble(firstNum) - Double.parseDouble(secondNum);


            case "*":
                return Double.parseDouble(firstNum) * Double.parseDouble(secondNum);

            case "/":
                return Double.parseDouble(firstNum) / Double.parseDouble(secondNum);

        }
        return 0;
    }

    private void refreshText(String text) {
        showText = text;
        **txt.setText(showText);**
    }

    private  void refreashOperate(String new_result){
        result  = new_result;
        firstNum = result;
        secondNum = "";
        operator = "";
    }

    private void clear() {
        refreshText("");
        refreashOperate("");
    }
}

下面是我的布局文件


<GridLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:rowCount="6"
    android:columnCount="4"
    android:padding="5dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:gravity="center"
        android:text="计算器"
        android:textSize="20sp"
        android:background="#EEEEEE">
    TextView>

    <TextView
        android:id="@+id/tv01"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:lines="2"
        android:gravity="right|bottom"
        android:text="0"
        android:textSize="50dp">
    TextView>

    <Button
        android:id="@+id/btn_cancel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_columnSpan="4"
        android:text="清除"
        android:textSize="26sp"
        android:layout_margin="8dp">
    Button>

    <Button
        android:id="@+id/one"
        android:text="1"
        android:textSize="26sp"
        android:layout_margin="5dp">
    Button>

    <Button
        android:id="@+id/two"
        android:text="2"
        android:textSize="26sp"
        android:layout_margin="5dp">
    Button>

    <Button
        android:id="@+id/three"
        android:text="3"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/add"
        android:text="+"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/four"
        android:text="4"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/five"
        android:text="5"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/six"
        android:text="6"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/minus"
        android:text="-"
        android:textSize="26sp"
        android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/seven"
    android:text="7"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/eight"
    android:text="8"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/nine"
    android:text="9"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/multiply"
    android:text="*"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/point"
    android:text="."
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/zero"
    android:text="0"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/denyu"
    android:text="="
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

    <Button
        android:id="@+id/chuyu"
    android:text="/"
    android:textSize="26sp"
    android:layout_margin="5dp">
Button>

GridLayout>

txt的定义重复了,且只初始化了oncreate中定义的,但是其他函数中使用的却是外层定义的txt,而外层的txt是没有初始化的,所以报错了,修改如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private  TextView txt;
    private  String firstNum = "";
    private  String operator = "";
    private  String secondNum = "";
    private  String result = "";
    private  String showText = "";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 去掉重复定义
        txt =findViewById(R.id.tv01);
        // 其他代码不变
    }
    
    // 其他代码不变
}

img

参考GPT和自己的思路:

根据报错日志可以看到,在MainActivity.java文件的第105行处,引发了NullPointerException异常,这是因为尝试在一个null对象上调用了一个方法,也就是在null的TextView上调用了setText(java.lang.CharSequence)方法。

根据代码可以看到,在onCreate()方法中,TextView txt已经被声明并赋值为findViewById(R.id.tv01)的返回值,但在后面的方法中,又声明了一个同名的局部变量TextView txt,并赋值为findViewById(R.id.tv01)的返回值,导致在refreshText()方法中,实际上使用的是一个null的局部变量txt。

解决方法是将onCreate()方法中的声明TextView txt改为:txt = findViewById(R.id.tv01)。这样就不会再出现空指针异常了。

参考GPT和自己的思路:

根据报错日志,问题出在第105行,即:txt.setText(showText)。这个错误是由于在onCreate()方法中,你声明了一个局部变量TextView txt,覆盖了成员变量TextView txt,所以在refreshText()方法中调用成员变量TextView txt时,引用的是null值。解决方法是在onCreate()方法中修改TextView txt的声明,将TextView txt =findViewById(R.id.tv01)改为 txt = findViewById(R.id.tv01)。