我在我的应用的主要活动中有以下代码:
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告诉我缺少的类是
com.myself.foo.myapp.OtherClass
- 这是一个不存在的类。简单的类名是来自另一个包的类的名称,但它的前缀是我的包名。显然,这个课程永远不会被找到。
当我将鼠标悬停在我的代码中的OtherClass
构造函数调用上时,Eclipse会显示正确的类名,并带有正确的包前缀。
两个包都与源文件存在于同一源树中 - 相应的路径为:
~/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>没有零参数构造函数
确实如此 - OtherClass
的构造函数接受三个参数,如调用中提供的那样。
由于某种原因,JVM正在调用new OtherClass()
(零参数),这与该类的任何已知构造函数都不匹配。如果OtherClass
驻留在不同的包中,则JVM会尝试在当前包中找到名为OtherClass
的类,其中包含匹配的构造函数签名。但是,如果OtherClass
位于同一个包中,则JVM至少会选择正确的类,但显然找不到匹配的构造函数。
这引出了一个问题:是什么导致JVM查找零参数构造函数?
请注意,OtherClass
不是Android组件:它不是来自任何属于Android框架的类,并且不会在Manifest中的任何位置引用。 OtherClass
是Object
的直接后代,并实现了自定义接口。
答案 0 :(得分:0)
我相信我发现了错误。在导入新代码之前,该应用程序已经运行。
我导入的代码是一个在其主要活动中混合了UI和功能的应用。 OtherClass
是活动的精简版本,我只保留其功能。
OtherClass
最初称为MainActivity
,与我应用的主要活动相同。我使用Eclipse中的重构功能将其重命名为OtherClass
。< / p>
令我惊讶的是,我在我的清单中找到了以下内容:
<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>
显然,两个相同的类名(包名称除外)与本地引用一起使Eclipse混淆,它更改了Manifest中的名称(它本应保持不变)。这就解释了原因:
com.myself.foo.myapp.OtherClass
丢失的原始邮件是因为此处的软件包是应用程序的默认软件包,因为它的清单。OtherClass
以确保找到它之后,Android仍然期望这个类是一个Activity,它(与其他Android系统组件一样)应该有一个零参数构造函数。将我的清单中的活动名称更改回MainActivity
后,错误就消失了。
经验教训:当不同包中的两个类具有相同的简单名称和时,对这些类有本地引用,重命名其中一个可能会混淆Eclipse。
建议:在重构之前提交所有内容。重构后,查看差异并查看更改是否正确。这可以节省您几小时的调试时间!