# wrong, FQN is needed
java Foon
# wrong, there is no `com/acme/example` folder in the current working directory
java com.acme.example.Foon
# wrong, similar to above
java -classpath . com.acme.example.Foon
# fine; relative classpath set
java -classpath ../../.. com.acme.example.Foon
# fine; absolute classpath set
java -classpath /usr/local/acme/classes com.acme.example.Foon
# 1 楼答案
如果类在包中,则必须
cd
到项目的根目录,并使用类的完全限定名(packageName.MainClassName)运行例如:
我的课程在这里:
我的主类的完全限定名为:
因此我
cd
返回根项目目录:然后发出
java
命令:这个答案是为了将新手java程序员从一个常见错误引起的挫折中解救出来,我建议您阅读公认的答案,以获得关于java类路径的更深入的知识
# 2 楼答案
当相同的代码在一台电脑上运行,但在另一台电脑上显示错误时,我发现的最佳解决方案是如下编译:
# 3 楼答案
帮助我的是在命令行上指定类路径,例如:
创建一个新文件夹,
C:\temp
创建临时文件。java在
C:\temp
中,其中包含以下类:在文件夹
C:\temp
中打开一个命令行,并编写以下命令来编译Temp类:运行已编译的Java类,添加
-classpath
选项,让JRE知道在哪里可以找到该类:# 4 楼答案
java <class-name>
命令语法首先,您需要了解使用
java
(或javaw
)命令启动程序的正确方法正常语法是:
其中
<option>
是命令行选项(以“-”字符开头),<class-name>
是完全限定的Java类名,<arg>
是传递给应用程序的任意命令行参数1-在这个答案的末尾描述了一些其他语法
类的完全限定名(FQN)按照惯例编写,就像在Java源代码中一样;e、 g
但是
java
命令的某些版本允许您使用斜杠而不是句点;e、 g它(令人困惑地)看起来像一个文件路径名,但不是一个。请注意,术语完全限定名是标准的Java术语。。。不是我编造出来让你困惑的东西:-)
下面是一个
java
命令的示例:上述操作将导致
java
命令执行以下操作:com.acme.example.ListUsers
类的编译版本李>main
方法,该方法具有public static void main(String[])
给出的签名、返回类型和修饰符。(注意,方法参数的名称不是签名的一部分。)李>String[]
传递给它李>Java找不到类的原因
当您收到消息“无法找到或加载主类…”时,这意味着第一步失败了。
java
命令无法找到该类。事实上,“…”消息中将包含java
正在查找的完全限定类名那么为什么它可能找不到类呢
原因#1-您在classname参数中犯了一个错误
第一个可能的原因是您可能提供了错误的类名。(或…正确的类名,但格式错误。)考虑到上面的示例,这里有多种指定类名的错误方法:
示例#1-一个简单的类名:
当类在包(如
com.acme.example
)中声明时,必须使用完整的类名,包括java
命令中的包名;e、 g示例#2-文件名或路径名而不是类名:
示例#3-大小写不正确的类名:
示例4——打字错误
示例#5-源文件名(Java 11或更高版本除外;见下文)
示例#6-您完全忘记了类名
原因#2-未正确指定应用程序的类路径
第二个可能的原因是类名正确,但是
java
命令找不到该类。要理解这一点,您需要理解“类路径”的概念。Oracle文档对此进行了解释:所以。。。如果正确指定了类名,那么接下来要检查的是是否正确指定了类路径:
java
命令时生效的命令行和/或CLASSPATH环境变量。检查目录名和JAR文件名是否正确李>java
命令时有效的当前目录李>;
,在其他平台上为:
。如果您的平台使用了错误的分隔符,您将不会收到明确的错误消息。相反,您将在路径上得到一个不存在的文件或目录,该文件或目录将被静默忽略。)李>原因#2a-类路径上的目录错误
当您将目录放在类路径上时,它在概念上对应于限定名称空间的根。通过将完全限定名映射到路径名,类位于该根目录下的目录结构中。因此,例如,如果“/usr/local/acme/classes”位于类路径上,那么当JVM查找名为
com.acme.example.Foon
的类时,它将查找具有以下路径名的“.class”文件:如果将“/usr/local/acme/classes/com/acme/example”放在类路径上,那么JVM将无法找到该类
原因#2b-子目录路径与FQN不匹配
如果类FQN为
com.acme.example.Foon
,则JVM将在目录“com/acme/example”中查找“Foon.class”:如果您的目录结构与按照上述模式命名的包不匹配,JVM将找不到您的类
如果您试图通过移动类来重命名一个类,那么也会失败。。。但异常stacktrace将有所不同。它可能会这样说:
因为类文件中的FQN与类装入器期望找到的内容不匹配
举一个具体的例子,假设:
com.acme.example.Foon
类/usr/local/acme/classes/com/acme/example/Foon.class
/usr/local/acme/classes/com/acme/example/
然后:
注:
-classpath
选项可以缩短为-cp
。请检查相应的手动条目中的java
、javac
等等李>原因#2c-类路径中缺少依赖项
类路径需要包括应用程序所依赖的所有其他(非系统)类。(系统类是自动定位的,您几乎不需要关心这一点。)为了正确加载主类,JVM需要找到:
(注意:JLS和JVM规范允许JVM“延迟”加载类,这可能会影响引发类装入器异常的时间。)
原因#3-该类已在错误的包中声明
偶尔会有人将源代码文件放入 源代码树中的文件夹错误,或者遗漏了
package
声明。如果在IDE中执行此操作,IDE的编译器将立即告诉您。类似地,如果您使用一个合适的Java构建工具,该工具将以检测问题的方式运行javac
。但是,如果您手工构建Java代码,则可以这样做:编译器不会注意到问题,并且生成的“.class”文件不在您期望的位置还是找不到问题
有很多东西需要检查,很容易漏掉一些东西。尝试将
-Xdiag
选项添加到java
命令行(作为java
之后的第一件事)。它将输出关于类加载的各种信息,这可能会为您提供关于真正问题是什么的线索也可以考虑从网站、文档等中复制和粘贴不可见或非ASCII字符引起的可能问题。考虑两个字母或符号看起来相同的“同形异义词”…但事实并非如此
如果
META-INF/*.SF
中的签名无效或不正确,则可能会遇到此问题。你可以试着打开门。在您最喜欢的ZIP编辑器中使用jar,并从META-INF
中删除文件,直到您只有MANIFEST.MF
。但是,一般不建议这样做。(无效的签名可能是有人将恶意软件注入原始签名JAR文件的结果。如果删除无效的签名,您的应用程序将受到恶意软件的感染!)推荐的方法是获取具有有效签名的JAR文件,或者从(真实的)原始源代码中重建它们最后,如果
MANIFEST.MF
文件中存在语法错误(请参见https://stackoverflow.com/a/67145190/139985),显然会遇到这个问题java
的可选语法使用
java command
启动Java程序有三种可选语法用于启动“可执行”JAR文件的语法如下:
例如
入口点类的名称(即
com.acme.example.ListUser
)和类路径在JAR文件的清单中指定从模块(Java 9及更高版本)启动应用程序的语法如下:
entrypoint类的名称由
<module>
本身定义,或者由可选的<mainclass>
给出从Java 11开始,您可以使用
java
命令使用以下语法编译和运行单个源代码文件:其中
<sourcefile>
是(通常)后缀为“.java”的文件有关更多详细信息,请参阅您正在使用的Java版本的
java
命令的官方文档IDE
典型的JavaIDE支持在IDEJVM本身或子JVM中运行Java应用程序。它们通常不受这个特殊异常的影响,因为IDE使用自己的机制来构造运行时类路径、识别主类并创建
java
命令行但是,如果您在IDE后面进行操作,则仍然可能发生此异常。例如,如果您以前在Eclipse中为Java应用程序设置了应用程序启动器,然后将包含“main”类的JAR文件移动到文件系统中的不同位置,而不告诉Eclipse,Eclipse将不自觉地以错误的类路径启动JVM
简言之,如果您在IDE中遇到此问题,请检查诸如过时的IDE状态、损坏的项目引用或损坏的启动器配置之类的情况
IDE也有可能会感到困惑。IDE是由许多相互作用的部分组成的极其复杂的软件。其中许多部分采用各种缓存策略,以使IDE作为一个整体具有响应性。这些有时会出错,一个可能的症状是启动应用程序时出现问题。如果您怀疑可能会发生这种情况,那么值得尝试重新启动IDE、重建项目等其他方法
其他参考资料
# 5 楼答案
如果您的源代码名是HelloWorld。java,编译后的代码将是
HelloWorld.class
如果使用以下方法调用该错误,则会出现该错误:
相反,请使用以下命令:
# 6 楼答案
带包装
如果源代码中有
package
关键字(主类在包中定义),则应使用类的全名(packageName.MainClassName
)在层次目录上运行它假设有一个源代码文件(Main.java):
要运行此代码,应将
Main.Class
放在类似于包的目录中:然后将终端的当前目录更改为项目的根目录:
最后,运行以下代码:
无包装
如果源代码名上没有任何包,则可能是错误的命令。假设编译后java文件名为
Main.java
:您编译的代码将是
Main.class
如果使用以下方法调用该错误,则会出现该错误:
相反,请使用以下命令: