试图对空对象引用错误调用虚拟方法int java.lang.integer.intvalue()?

nlejzf6q  于 2021-07-03  发布在  Java
关注(0)|答案(1)|浏览(327)

这个问题在这里已经有答案了

什么是nullpointerexception,如何修复它(12个答案)
24天前关门。
对于android开发来说,这是一个相当新的问题,因此很容易解决。
我的应用程序有一个recyclerview,它显示一些要填充的空字段,每个字段都有一个“delete”按钮。当我按DeleteComponent按钮时,会收到以下错误消息:

java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference

我目前的主要活动如下

package com.example.recipecalculator;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity implements IngredientsAdapter.IngredientVH.ItemDeleter {

    private RecyclerView recyclerView;
    private RecyclerView.LayoutManager layoutManager;
    public static IngredientsAdapter adapter;
    public static List<Ingredient> ingredients = new ArrayList<>();

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

        ingredients.add(new Ingredient(0, null, null));

        recyclerView = findViewById(R.id.ingredients_recyclerView);
        layoutManager = new LinearLayoutManager(this);
        adapter = new IngredientsAdapter(this, this);

        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setAdapter(adapter);
    }

    public void addIngredient(View view) {
        ingredients.add(new Ingredient(0, null, null));
        adapter.notifyDataSetChanged();
    }

    @Override
    public void deleteIngredient(Integer position){
        Log.d("CS50", "MAIN ACTIVITY CALLBACK INVOKED");
        ingredients.remove(position);
        adapter.notifyItemRemoved(position);
    }
}

我的适配器类是这样的

package com.example.recipecalculator;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;
import java.util.List;

public class IngredientsAdapter extends RecyclerView.Adapter<IngredientsAdapter.IngredientVH> {

    private Context context;
    private IngredientVH.ItemDeleter deleter;

    public static class IngredientVH extends RecyclerView.ViewHolder {

        public EditText quantity;
        public Spinner unitOfMeasure;
        public EditText ingredientName;
        public Button deleteIngredient;
        public ItemDeleter deleter;

        public IngredientVH(View view, Context context, ItemDeleter deleter){
            super(view);
            this.quantity = view.findViewById(R.id.quantity);
            this.ingredientName = view.findViewById(R.id.ingredient_name);
            this.unitOfMeasure = view.findViewById(R.id.unitOfMeasure_spinner);
            this.deleteIngredient = view.findViewById(R.id.delete_icon);

            ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(context,
                    R.array.units_of_measure, android.R.layout.simple_spinner_item);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            unitOfMeasure.setAdapter(adapter);

            Integer position = (Integer) quantity.getTag();
            this.deleter = deleter;

            deleteIngredient.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    deleter.deleteIngredient(position);
                }
            });
        }

        public interface ItemDeleter {
            void deleteIngredient(Integer position);
        }
    }

    public IngredientsAdapter(Context context, IngredientVH.ItemDeleter deleter){
        super();
        this.context = context;
        this.deleter = deleter;
    }

    @NonNull
    @Override
    public IngredientVH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.ingredient_row, parent, false);
        return new IngredientVH(view, context, deleter);
    }

    @Override
    public void onBindViewHolder(@NonNull IngredientVH holder, int position) {
        holder.quantity.setTag(position);
    }

    @Override
    public int getItemCount() {
        return MainActivity.ingredients.size();
    }
}

很明显,这与使用deleteComponent按钮单击传递项目位置有关,但无法确定它是什么。
干杯!

wsxa1bj1

wsxa1bj11#

@Override
public void deleteIngredient(Integer position){
    Log.d("CS50", "MAIN ACTIVITY CALLBACK INVOKED");
    ingredients.remove(position);
    adapter.notifyItemRemoved(position);
}

请注意,您传递了一个 Integer 使用这种方法。与原始相反 int , Integers 可以是 null . 如果用 position 有一个 null 价值观,这是行不通的:

ingredients.remove(position);

为什么?因为配料是 List 以及所需的参数 remove() 是一个 int .
这意味着当编译器尝试自动取消对空值的装箱时 Integer 到一个 int ,通过呼叫 intValue() 在上面。与任何java空对象一样,对它的任何调用都会抛出 NullPointerException . 它将永远无法自动取消一个未初始化的 Integer 无论如何(哪个数字应该为空?)
为了解决这个问题,你应该保证 Integer position 变量不是 null 当你打电话的时候 deleteIngredient() . 这样,拆箱就可以 int 将是有效的,您将避免错误。
你必须检查一下为什么这个职位会回到这里。。。

Integer position = (Integer) quantity.getTag();

…正在得到一个 null 价值观。
另一种避免错误的机制(但不是主要问题的真正解决方案)可能是在自动取消装箱之前检查位置是否有效:

@Override
public void deleteIngredient(Integer position)
{
    if (position==null)
        return; // maybe some logs here

    Log.d("CS50", "MAIN ACTIVITY CALLBACK INVOKED");
    ingredients.remove(position);
    adapter.notifyItemRemoved(position);
}

相关问题