我写了下面的Java源文件( Hello.java
):
package com;
public class Hello {
public static void main(String[] args) {
System.out.println("Hello!");
}
}
我这保存到C:/tmpjava/Hello.java
。
在命令行中,我浏览到该目录,并运行javac Hello.java
。 然后我跑dir
:
然后,从我只是跑在同一目录javac
距离,我运行java Hello.class
并获得:
Exception in thread "main" java.lang.NoClassDefFoundError: Hello/class
Caused by: java.lang.ClassNotFoundException: Hello.class
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
Could not find the main class: Hello.class. Program will exit.
这里发生了什么?!? 如何javac
运行很好,但不是java
?
你的类Hello
属于包com
。 所以,你的类的全名是com.Hello
。 当您使用的命令行的java调用程序,你应该提供包含您的类的完全限定类名称main
方法和省略的.class,就像这样:
java com.Hello
Java程序需要这个完全限定类名来了解你指的是哪一个类。
但是,你有另一个问题。 Java程序包定位,子包,以及属于他们使用的文件系统的类。 所以,如果你有一个像封装结构com.Hello
,java程序希望找到一个名为COM名为Hello.class类文件,如:COM / Hello.class。 事实上,你可以看到在这个行为Exception
,你看; 你正确使用Hello.class,哪个Java将其解释为指定包 Hello
,和一类名为class
,并正在寻找的目录结构你好/类 :
java.lang.NoClassDefFoundError:你好/班
但是,编译器javac的默认情况下不设置此目录结构。 请参阅用于javac文档 ,但最重要的一点是:当你做你的编译,您可以指定使用一个目标目录-d
标志:
-d目录
设置类文件的目标目录。 目标目录必须已经存在; javac的不会创建目标目录。 如果一个类是包的一部分,javac的放在一个子目录反映包名的类文件,根据需要创建目录。 例如,如果指定-dc:\ myclasses和类被称为com.mypackage.MyClass,那么该类文件名为C:\ myclasses \ COM \ mypackage中\ MyClass.class。
如果没有指定-d,javac的把类文件在同一目录作为源文件。
以粗体显示的最后一位是初学者很多混乱的来源,是你自己的问题的一部分。
所以,你有两个选择:
在你的情况下,如果你提供的当前目录作为目标目录,像这样的罚款(周期.
意味着当前目录 ):
javac -d . Hello.java
如果你调用编译器就是这样,它会为你创建com目录,并把你的编译的类文件在里面,在Java程序需要找到它的方式。 然后,当你运行java如上,从C:\ tmpJava,你的程序应该执行。
你可以设置使用与包结构的目录结构中的源代码:把你的源文件Hello.java一个名为com的目录内,你的情况:C:\ tmpJava \ COM \ Hello.java。 现在,从C:\ tmpJava你可以运行你的javac编译如下:
javac com\Hello.java
您还没有提供的-d
标志,但是这很好,因为你自己创建的目录结构,并从上面的文档再次引用:
如果没有指定-d,javac的把类文件在同一目录作为源文件。
同样,当你运行java如上,你的程序应该执行。
请注意,此第二替代是一种通常通过Java编程人员使用:源代码文件中,反映了封装结构的目录结构进行组织。
在该说明中,我们已经忽略类路径的概念。 您还需要了解的是写Java程序,但在你的只是在当前目录编译程序的情况下 - 如果按照两个备选方案编译您的类时上面的一个 - 你可以逃脱不设置classpath中,因为默认情况下,Java程序具有当前目录中的类路径。 另一句名言,这种情况一方面源自于Java文档 :
-cp类路径
指定要搜索类文件的目录,JAR档案,ZIP压缩文件的列表。 类路径条目由分号(;)分隔。 指定-classpath或-cp覆盖CLASSPATH环境变量的任何设置。
如果-classpath和-cp未使用,CLASSPATH没有设置,则用户类路径由当前目录的(。)。
请注意,当你使用像Eclipse的IDE来运行Java代码,这主要是为您处理,但你还是会碰到类路径的问题。
Java命令的语法是:
java [classname]
不
java [filename]
java查找在其类路径中的一类,你提供的姓名的。 通常情况下,类路径包括当前目录,因此:
java Hello
...会发现Hello.class在当前目录,并运行其main()方法。
但是,如果类是在其他地方(如在一个.jar,或者在文件系统中的其他地方),你可以用CLASSPATH环境变量指定,或者在命令行:
java -cp build/classes Hello
java -cp build/jars/myjar.jar Hello
该类应该在C:\tmpjava\com\Hello.class
你应该从运行C:\tmpjava
: java -cp . com.Hello
java -cp . com.Hello
当你把一个类的包,它定义的类的文件结构。 即你的类在包com
应在文件夹中com
java的-classpath C:\ tmpjava com.Hello