添加了新的(部分重构的)代码,现在为从未存在的类获取ClassNotFoundException

时间:2017-05-14 16:20:05

标签: java android eclipse adt

我在我的应用的主要活动中有以下代码:

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中的任何位置引用。 OtherClassObject的直接后代,并实现了自定义接口。

1 个答案:

答案 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。

建议:在重构之前提交所有内容。重构后,查看差异并查看更改是否正确。这可以节省您几小时的调试时间!