英文:
javac and java command in terminal
问题
-
当我在IntelliJ终端中输入以下内容时:
javac MyClass.java
java MyClass
错误:找不到或加载主类MyClass
java.lang.NoClassDefFoundError:myPackage/myClass(错误名称:MyClass)
-
当我在IntelliJ终端中输入以下内容时:
javac MyClass.java
java MyClass.java
程序成功运行,没有任何错误。
有人可以解释一下为什么会发生这种情况吗?
英文:
I have a question below. I use JDK 17.
this is my codes.
package myPackage;
public class myClass {
public static void main(String[] args){
System.out.println("test");
}
}
1.When I write in IntelliJ terminal:
javac MyClass.java
java MyClass
Error:Could not find or load main class MyClass
java.lang.NoClassDefFoundError: myPackage/myClass(wrong name: MyClass)
2.When I write in IntelliJ terminal:
javac MyClass.java
java MyClass.java
Program run succesfully without any error.
May somebody explain me why this happen?
答案1
得分: 1
java MyClass
这将把参数视为“完全限定名称”(Fully Qualified Name),然后在类路径(classpath)中查找该类型。它通过将FQN转换为文件名(用斜杠替换所有点,并在末尾加上.class
),例如/MyClass.class
,然后将该字符串附加到类路径上的所有条目来执行此操作。这通常成功,因为.
(当前目录)很可能在类路径上,而且确实存在./MyClass.class
,这是一个真实的文件。
然而,随后会失败:这个类文件被打开,读取,然后Java才注意到:哦,这是一个描述myPackage.myClass
的类文件,而我想要的是MyClass
,所以虽然找到了文件,但我不会运行它。
要使其正常工作,你需要运行java myPackage.myClass
(注意这里的小写m),它将在所有类路径中寻找/myPackage/MyClass.class
。为使其工作,需要同时满足[A]找到文件以及[B]该文件必须是包含package myPackage; .... class myClass {}
的文件编译生成的产品。
java MyClass.java
这是完全不同的情况;javac将其视为一个特殊情况(自Java 11以来的新功能),仅用于非常基本的“我正在学习Java”或“创建一个快速演示项目”。这绕过了构建完整应用程序的所有尝试,缩短了该过程:它打开该文件,编译它,并运行其中标记为public
的类,而不考虑其实际名称或包。
这种“模式”会被触发,因为参数以.java
结尾并且该文件存在。
这确实有效,并能成功运行你的代码。
英文:
> java MyClass
This treats the argument as a Fully Qualified Name and looks that type up in the classpath. It does this by translating the FQN to a filename (replace all dots with slashes and stick .class
at the end of it), so, /MyClass.class
, and then looks for that file by appending that string to all entries on the classpath. This succeeds, in that .
(the current directory) is likely on your classpath, and there is indeed ./MyClass.class
- that is a real file.
However, this then fails: This class file is opened, read, and java only then notices: Ah, this is a class file describing myPackage.myClass
, and I wanted MyClass
, so while I found the file, I'm not going to run it.
To make it work, you'd have to run java myPackage.myClass
(note the lower case m here), which will look for /myPackage/MyClass.class relative to all classpaths. For it to work it needs to [A] find the file, and [B] that file needs to be the product of compiling a file containing package myPackage; .... class myClass {}
in it.
> java MyClass.java
This is something completely different; javac treats this is as a special case (new functionality since Java 11), solely intended for very bare bones "I am learning java" / "Making a quick demo project". This bypasses all attempts to build a complete application and shortcuts the process: It opens that file, compiles it, and runs that class that was in it that was public
, regardless of its actual name or package.
This 'mode' is triggered because the argument ends in .java
and that file exists.
This does work and runs your code fine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论