带有继承类的Java NoClassDefFoundError

时间:2013-07-15 08:36:10

标签: java noclassdeffounderror

我最近开始学习Java但是我遇到了一些与NoClassDefFoundError相关的问题。我试图从这个网站和其他地方研究解决方案,但仍然无法解决它们。我使用CLASSPATH环境变量集从Windows 7命令提示符运行我的程序,而不是为每个程序运行定义它。它设置为C:。为了排除故障,我创建了一个具有简化目录结构的测试包。

C:\test,我有Shape.javaCircle.javaShape.java看起来像这样:

package test;

class Shape {
    void draw() { System.out.println("Drawing a new shape"); }
}

Circle.java看起来像这样:

package test;

public class Circle extends Shape {
        public static void main(String[] args) {
        Circle round = new Circle();
        round.draw();
    }
}

如果我在命令提示符中使用{/ 1>这样的操作从Shape.java编译Circle.javaC:\

C:\>javac test\Shape.java 
C:\>javac test\Circle.java

并运行已编译的Circle.class文件,如

C:\java test\Circle

我得到了我期望的输出:

Drawing a new shape

但是,如果我从Shape.java内部编译Circle.javaC:\test

C:\test>javac Shape.java 
C:\test>javac Circle.java

然后尝试从

之类的任何位置运行Circle.class
C:\test>java Circle

或者像这样

C:\> java test\Circle

我收到以下错误消息。

Exception in thread "main" java.lang.NoClassDefFoundError: Circle (wrong name: t
est/Circle)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:792)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:14
2)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)

有人可以解释为什么JAVA文件是从C:\test文件夹中编译的,但编译后的Circle文件会产生错误吗?我的CLASSPATH有问题吗?感谢阅读和希望即将推出的解决方案!

编辑:我做了一些测试,结果证明,如果我从Shape.java目录编译Circle.javaC:\test文件,但是从{{1}运行它目录,它的工作原理。这会改变什么吗?

编辑2:经过更多测试后,事实证明,只要我使用命令java test.Circle,我就可以在C:\ test目录中编译和运行Shape.java和Circle.java文件。我误解了JVM查找类的方式。我现在明白它在分析包导入语句时使用与编译器相同的方法。

3 个答案:

答案 0 :(得分:1)

只要你有一个类路径,你就可以在系统的任何地方。

只有这样,java VM才能扫描类路径,并在包test.Circle中找到类test

因此,正确的执行是java test.Circle(总是),并且类路径需要指向可用\test\Circle.class的东西。检查Circle.class是否符合预期。

答案 1 :(得分:0)

您的类路径代表您存储类的位置。因为您已将类路径设置为c:\。因此,当您使用java命令启动jvm时,它将从c:\加载所需的类。当您从C:编译并运行程序时,您的代码正在运行,因为这些类将被编译并且在这种情况下将出现在C:中,所以没问题。但是当您从c:\test编译类时,您的.class文件将出现在c:\ test中,但您的类路径将只加载c:\而不是c:\test的类。

答案 2 :(得分:0)

编译,使用

javac -d . Shape.java
javac -d . Circle.java

运行

java test.Circle

-d用于选择目标目录
.表示当前目录 因此,在您当前的Directry C:\test\中,当您编译java文件时,将创建一个名为test(包名称)的新目录,并且类文件将在其中。 即。C:\test\test\Shape.javaC:\test\test\Circle.java