Attempt to invoke virtual method ‘…’ on a null object reference尝试在空对象引用上调用…虚拟方法
遇到了四次这样的提示,逐个解析之。
一、只声明,未创建。
如下代码:
public class SortMallFragment extends Fragment {
... ...
private ArrayList<Fragment> rightFragments;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
//rightFragments = new ArrayList<>();
for (int i = 0; i < leftTitles.length; i++){
rightFragments.add(RightSortMallFragment.newInstance(leftTitles[i],"0"));
}
... ...
}
}
错误提示为:Attempt to invoke virtual method ‘boolean java.util.ArrayList.add(java.lang.Object)’ on a null object reference,即:尝试在空对象引用上调用虚拟方法“boolean java.util.ArrayList.add(java.lang.Object)”。
主要原因对象rightFragments只声明,未创建,是空的(null),当调用其add()方法时,就不符合逻辑了。改正方法就是将上述代码中的双斜杠去掉,即创建一下对象就可以了。
二、循环过程中无法生成对象。
如下代码:
for (int i = 0; i<5; i++){
LinearLayout v0 = (LinearLayout) tabLayout.getChildAt(i);
LinearLayout v1 = (LinearLayout) v0.getChildAt(0);
... ...
}
若tabLayout中只有2个子项,而循环要进行5轮。等循环到第3轮时,v0就是一个空对象,调用其getChildAt()方法,试图从里面拿出些什么,恐怕什么也拿不出来,所以报错:
Attempt to invoke virtual method ‘android.view.View android.view.ViewGroup.getChildAt(int)’ on a null object reference
这时虽然语法不错,但逻辑肯定有问题,应朝这个方向寻找问题。
三、HashMap中本无目标对象,却“强行”取出,还马上使用。
如下代码:
public class SkyPlatform {
public static HashMap<Integer, BuyInfoSortMall> tempInfoSortMall = new HashMap<>();
}
......
// tempInfoSortMall是SkyPlatform类中的HashMap对象
// bism是“存储类”BuyInfoSortMall
BuyInfoSortMall bism = SkyPlatform.tempInfoSortMall.get(id);
//获取tempInfoSortMall中对应id对应类中的Quantity(数量)值
int count = bism.getQuantity();
......
此时若tempInfoSortMall不存在id对应的类对象,取到的“假对象”bism的getQuantity()就会什么也得不到,就会报错。解决方法就是之前做一下bism是否为空的判断,并作不同处理。
四、调用了“空的”上下文(Context)
代码如下:
public static void displayDirctory() {
String mDataRootPath = Environment.getExternalStorageDirectory().
getPath(); // 获取公共外部存储路径字符串
Log.d("公共外部存储路径”:",mDataRootPath);
String mDataRootPath1 = context.getExternalFilesDir("").
getAbsolutePath(); // 获取私有外部存储路径字符串
Log.d("私有外部存储路径”:",mDataRootPath1);
}
代码中的context没有被“充实”,是空的,调用其方法时必然产生错误。
解决方法1:
重写自己的Application类:MyApplication继承自Application类,在其中构造一个全局Context,其它地方使用时调用即可:
public class MyApplication extends Application {
public static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
public static Context getContext() {
return context;
}
}
调用:
String mDataRootPath1 = MyApplication.getContext().getExternalFilesDir("").
getAbsolutePath();
同时在AndroidManifest的application标签下进行指定就可以了:
<application
android:name="com.example.test.util.MyApplication"
这种方法通用性强,一次书写,到处调用,但全局Context,可能体量会大一些吧。
解决方法2
写方法时加入参数Context,在“活动”中调用时配给参数(this或其它Context参数)。
方法代码:
public class FilesUtils {
public static void displayDirctory(Context context) {
String mDataRootPath = Environment.getExternalStorageDirectory().
getPath(); // 此路径:
Log.d("公共外部存储路径”:",mDataRootPath);
String mDataRootPath1 = context.getExternalFilesDir("").
getAbsolutePath(); // 此路径:
Log.d("私有外部存储路径”:",mDataRootPath1);
}
}
调用代码:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
String FilesUtils.displayDirctory(this);
...
}
}
解决方法3:
直接使用“this”。代码写在“Activity”中,需要上下文处写上“this.”,代码:
public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
String mDataRootPath1 = this.getExternalFilesDir("").
getAbsolutePath();
...
}
}
此方法简单,但在复杂的调用中,显得不太好使了。
其它方法有待研究。
五、小结
出现“Attempt to invoke virtual method ‘…’ on a null object reference”提示,首先说明有一个空对象,其次还要调用这个对象的方法,代码形如:“空对象.方法()”。这好比还没发工资,就拿着“钱影子”去买东西,逻辑上很荒谬。解决的方向应该是仔细研究这个“空对象”的由来。