1

我最近开始学习 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();
    }
}

如果我在命令提示符下使用类似的操作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.javaandCircle.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.javaCircle.java文件但从C:\test目录运行它C:\,它可以工作。这有什么改变吗?

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

4

3 回答 3

1

你可以在系统上的任何地方,只要你有一个以 .

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

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

于 2013-07-15T08:40:18.893 回答
0

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

于 2013-07-15T08:41:57.010 回答
0

编译,使用

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

跑步

java test.Circle

-d用于选择目标目录
.是指当前目录所以在当前目录中C:\test\,当您编译java文件时,test将创建一个名为(包名)的新目录,其中将包含类文件。IE。
C:\test\test\Shape.javaC:\test\test\Circle.java

于 2013-07-15T09:03:40.230 回答