添加了新的(部分重构的)代码,现在获取从未存在的 class 的 ClassNotFoundException
Added new (partially refactored) code, now getting ClassNotFoundException for a class that never existed
我的应用程序 activity 中有以下代码:
package com.myself.foo.myapp;
import com.someotherfellow.hisapp.OtherClass;
// more imports here
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object bar = new OtherClass(blah, this, YetAnotherClass.class);
// ...
}
}
当我构建并启动它时(使用 Eclipse 和 ADT),应用程序崩溃并出现未处理的 ClassNotFoundException
。 logcat 告诉我缺少的 class 是
com.myself.foo.myapp.OtherClass
——这是一个不存在的class。简单的 class 名称是来自另一个包的 class 的名称,但它以我的包名称为前缀。显然 class 将永远找不到。
当我将鼠标悬停在我的代码中 OtherClass
的构造函数调用上时,Eclipse 显示正确的 class 名称和正确的包前缀。
这两个包都存在于与源文件相同的源树中——各自的路径是:
~/src/myapp/src/com/myself/foo/myapp/MainActivity.java
~/src/myapp/src/com/someotherfellow/hisapp/OtherClass.java
是什么导致了这种行为,我该如何解决?
编辑: 出于好奇,我重构了代码,将 OtherClass
移动到 Android 试图找到它的包中。现在我得到:
java.lang.InstantiationException: java.lang.Class<com.myself.foo.myapp.OtherClass> has no zero argument constructor
确实如此——OtherClass
的构造函数采用调用中提供的三个参数。
由于某种原因,JVM 似乎正在调用 new OtherClass()
(参数为零),它与 class 的任何已知构造函数都不匹配。如果 OtherClass
驻留在不同的包中,JVM 会尝试在当前包中查找名为 OtherClass
且具有匹配构造函数签名的 class。但是,如果 OtherClass
在同一个包中,JVM 至少会选择正确的 class,但显然找不到匹配的构造函数。
这引出了一个问题:是什么导致 JVM 寻找零参数构造函数?
请注意,OtherClass
不是 Android 组件:它不是来自属于 Android 框架的任何 classes,也没有被引用清单中的任何位置。 OtherClass
是 Object
的直系后代并实现了自定义接口。
我相信我找到了错误。在我导入新代码之前,该应用程序已经运行。
我导入的代码是一个混合了 UI 和主要 activity 功能的应用程序。 OtherClass
是 activity 的精简版,其中我只保留了功能。
OtherClass
原来叫MainActivity
,和我的主activity一样。我改名为OtherClass
] 在 Eclipse 中使用重构功能。
令我惊讶的是,我在清单中发现了以下内容:
<activity
android:name=".OtherClass"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
显然,两个相同的 class 名称(包名称除外)与本地引用一起混淆了 Eclipse,它更改了 Manifest 中的名称(它应该保持不变) .这就解释了为什么:
- 关于
com.myself.foo.myapp.OtherClass
丢失的原始消息是因为根据其清单,此处的包是应用程序的默认包。
- 在移动
OtherClass
以确保找到它之后,Android 仍然期望这个 class 是一个 Activity,它(像其他 Android系统组件)应该有一个零参数构造函数。
一旦我将清单中 Activity 的名称改回 MainActivity
,错误就消失了。
经验教训: 当不同包中的两个 class 具有相同的简单名称时 和 有对的本地引用这些 classes,重命名其中之一可能会混淆 Eclipse。
建议:重构前提交所有内容。重构后,查看差异并查看更改是否正确。这可能会为您节省数小时的调试时间!
我的应用程序 activity 中有以下代码:
package com.myself.foo.myapp;
import com.someotherfellow.hisapp.OtherClass;
// more imports here
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Object bar = new OtherClass(blah, this, YetAnotherClass.class);
// ...
}
}
当我构建并启动它时(使用 Eclipse 和 ADT),应用程序崩溃并出现未处理的 ClassNotFoundException
。 logcat 告诉我缺少的 class 是
com.myself.foo.myapp.OtherClass
——这是一个不存在的class。简单的 class 名称是来自另一个包的 class 的名称,但它以我的包名称为前缀。显然 class 将永远找不到。
当我将鼠标悬停在我的代码中 OtherClass
的构造函数调用上时,Eclipse 显示正确的 class 名称和正确的包前缀。
这两个包都存在于与源文件相同的源树中——各自的路径是:
~/src/myapp/src/com/myself/foo/myapp/MainActivity.java
~/src/myapp/src/com/someotherfellow/hisapp/OtherClass.java
是什么导致了这种行为,我该如何解决?
编辑: 出于好奇,我重构了代码,将 OtherClass
移动到 Android 试图找到它的包中。现在我得到:
java.lang.InstantiationException: java.lang.Class<com.myself.foo.myapp.OtherClass> has no zero argument constructor
确实如此——OtherClass
的构造函数采用调用中提供的三个参数。
由于某种原因,JVM 似乎正在调用 new OtherClass()
(参数为零),它与 class 的任何已知构造函数都不匹配。如果 OtherClass
驻留在不同的包中,JVM 会尝试在当前包中查找名为 OtherClass
且具有匹配构造函数签名的 class。但是,如果 OtherClass
在同一个包中,JVM 至少会选择正确的 class,但显然找不到匹配的构造函数。
这引出了一个问题:是什么导致 JVM 寻找零参数构造函数?
请注意,OtherClass
不是 Android 组件:它不是来自属于 Android 框架的任何 classes,也没有被引用清单中的任何位置。 OtherClass
是 Object
的直系后代并实现了自定义接口。
我相信我找到了错误。在我导入新代码之前,该应用程序已经运行。
我导入的代码是一个混合了 UI 和主要 activity 功能的应用程序。 OtherClass
是 activity 的精简版,其中我只保留了功能。
OtherClass
原来叫MainActivity
,和我的主activity一样。我改名为OtherClass
] 在 Eclipse 中使用重构功能。
令我惊讶的是,我在清单中发现了以下内容:
<activity
android:name=".OtherClass"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
显然,两个相同的 class 名称(包名称除外)与本地引用一起混淆了 Eclipse,它更改了 Manifest 中的名称(它应该保持不变) .这就解释了为什么:
- 关于
com.myself.foo.myapp.OtherClass
丢失的原始消息是因为根据其清单,此处的包是应用程序的默认包。 - 在移动
OtherClass
以确保找到它之后,Android 仍然期望这个 class 是一个 Activity,它(像其他 Android系统组件)应该有一个零参数构造函数。
一旦我将清单中 Activity 的名称改回 MainActivity
,错误就消失了。
经验教训: 当不同包中的两个 class 具有相同的简单名称时 和 有对的本地引用这些 classes,重命名其中之一可能会混淆 Eclipse。
建议:重构前提交所有内容。重构后,查看差异并查看更改是否正确。这可能会为您节省数小时的调试时间!