gpt4 book ai didi

java - 空白类型的 Android ClassCastException

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:04:38 25 4
gpt4 key购买 nike

我遇到了一个奇怪的行为,我想我更多的是在寻找解释而不是解决方案(尽管也欢迎解决方案!)。

代码如下:

PackageManager pm = context.getPackageManager();
List<PackageInfo> pkgList = pm.getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES);
if (pkgList == null)
return null;
for (PackageInfo pkgInfo : pkgList) {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
// do some stuff, doesn't modify pkgInfo or appInfo or pkgList
}

在某些情况下,我会收到错误日志:

java.lang.ClassCastException: cannot be cast to android.content.pm.PackageInfo

报告行:

for (PackageInfo pkgInfo : pkgList)

奇怪的是,通常情况下,ClassCastException 通常看起来像 (AFAIK):

java.lang.ClassCastException: foo.bar.ClassA cannot be cast to foo.bar.ClassB

但是,我看到的错误是第一部分显示为空白。

我决定稍微研究一下,如果返回列表的函数在内部转换了错误的对象列表并返回它或其他什么,可能会发生一些类似的事情。所以我看了看:

ApplicationPackageManager.getInstalledPackages()

@SuppressWarnings("unchecked")
@Override
public List<PackageInfo> getInstalledPackages(int flags) {
try {
final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
PackageInfo lastItem = null;
ParceledListSlice<PackageInfo> slice;

do {
final String lastKey = lastItem != null ? lastItem.packageName : null;
slice = mPM.getInstalledPackages(flags, lastKey);
lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
} while (!slice.isLastSlice());

return packageInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}

好的,所以返回的列表是从 ParceledListSlice.populateList()...

填充的

ParceledListSlice.populateList()

public T populateList(List<T> list, Creator<T> creator) {
mParcel.setDataPosition(0);

T item = null;
for (int i = 0; i < mNumItems; i++) {
item = creator.createFromParcel(mParcel);
list.add(item);
}

mParcel.recycle();
mParcel = null;

return item;
}

所以项目是从 PackageInfo.CREATOR.createFromParcel()...

创建的

最后是 PackageInfocreator.createFromParcel

public static final Parcelable.Creator<PackageInfo> CREATOR
= new Parcelable.Creator<PackageInfo>() {
public PackageInfo createFromParcel(Parcel source) {
return new PackageInfo(source);
}

public PackageInfo[] newArray(int size) {
return new PackageInfo[size];
}
};

所以一切似乎都还好。它正在创建 PackageInfo 类型的 ParceledListSlice,因此在 populateList 中它正在创建一个 PackageInfo 项并将其放入PackageInfoList,即返回列表。所有类型/类对我来说都很好。

所以我的问题,

  1. 上述 ClassCastException 是如何发生的?
  2. 为什么错误消息会显示“空白”类型?
  3. 什么是可能的解决方案?

我正在考虑将列表作为 Object 的列表并检查“instanceof”,但我认为这也行不通,因为它会可能最后会说

ClassCastException: cannot be cast into java.lang.Object" or something.

任何有关如何发生这种情况的见解和解释都将不胜感激。

  1. Dalvik/JVM 只是搞砸了吗?
  2. 内存是否损坏?

我只能胡乱猜测 =)

最佳答案

如果你确定你在这一行得到了 ClassCastException

for (PackageInfo pkgInfo : pkgList)

当出现原因时 - pkgList 以某种方式包含不是 PackageInfo 类的值。我假设这是 NULL 值。为什么在 ClassCast 错误消息中看不到它,因为 NULL 对象的 className 只是空字符串。

现在,如何解决这个问题 - 使用手册 for 循环。 for each 循环在底层使用了 Iterator,因此您无法控制每次迭代中的类转换。但是如果你将使用这样的代码:

for (int i = 0; i < pkgList.length; i++) {
Object pkgInfoObj = pkgList.get(i);
if (pkgInfoObj instanceof PackageInfo) {
PackageInfo pkgInfo = (PackageInfo) pkgInfoObj;
ApplicationInfo appInfo = pkgInfo.applicationInfo;
// do some stuff, doesn't modify pkgInfo or appInfo or pkgList
}
}

您将能够控制类转换。

此外,您可以捕获 ClassCastException 并跳过此循环步骤到下一个步骤。

关于java - 空白类型的 Android ClassCastException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13020143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com