为什么编译器需要.java后缀,而解释器不需要';不需要。类后缀?

为什么编译器需要.java后缀,而解释器不需要';不需要。类后缀?,java,Java,编译Foo.java:javac Foo.java 要运行程序:JavaFoo 为什么编译器需要.java后缀,而解释器不需要.class后缀?java编译器采用文件名作为输入,因此Foo.java Java解释器采用完全限定的类名,并在类路径和当前目录中搜索该类。如果您使用java Foo.class,它将在包“Foo”中搜索名为“class”的类,如果该类位于默认包中,则返回NoClassDefFoundError,正如我从您的示例中了解到的那样Foo.java是文件名,而“Foo”只是类名

编译Foo.java:javac Foo.java

要运行程序:JavaFoo


为什么编译器需要
.java
后缀,而解释器不需要
.class
后缀?

java编译器采用文件名作为输入,因此Foo.java


Java解释器采用完全限定的类名,并在类路径和当前目录中搜索该类。如果您使用java Foo.class,它将在包“Foo”中搜索名为“class”的类,如果该类位于默认包中,则返回NoClassDefFoundError,正如我从您的示例中了解到的那样

Foo.java是文件名,而“Foo”只是类名(不是文件名)。默认的类加载器将在您当前的工作目录中搜索Foo.class文件并将其加载。

每种语言都有语法和语义,这些语法和语义将在类似各方之间建立规则和理解。比如英语中的单词、时态、动词等,简化了说英语的双方之间的交流。Java规范确定了编译器只能理解Java文件而解释器只能理解.class文件的语法和语义。

正如其他几个答案所解释的,Java编译器使用文件名作为参数,而解释器使用类名。因此,您将
.java
扩展名提供给编译器,因为它是文件名的一部分,但您不将其提供给解释器,因为它不是类名的一部分


但是,您可能会想,为什么他们不以不同的方式设计Java解释器,使其采用文件名呢?答案是类并不总是从
.class
文件加载。有时它们来自JAR档案,有时它们来自JAR档案,有时它们是由程序动态构建的,等等。类可以来自任何可以提供所需二进制数据的源。也许同一个类可以有来自不同来源的不同实现,例如,一个程序可能试图从URL加载某个类的最新版本,但如果失败,则会返回到本地文件。Java的设计者认为,当您试图运行一个程序时,最好不要担心必须跟踪定义您正在运行的类的源代码。您只需给出完全限定的类名,然后让Java(或者更确切地说,它的
类加载器
s)努力查找它。

补充David Zaslavsky的解释:

java源代码也不一定来自
.java
文件。我们可以有一个从不同字符流中获取源代码的编译器,如API
javax.tools.JavaCompiler


cmd行util
javac
恰好只用于文件源,因此它需要文件路径。

它不是文件名。注意,它是
javac-pkg/Foo.java
,但是
javapkg.Foo
。小程序像往常一样做一些心理上的事情。这是一个公平的观点,但是为了解释这个特殊的设计决策,您必须回顾一下Java 1.0,在Java 1.0中,
FileObject
抽象不存在,处理源代码的唯一方法是将其放入一个文件中(或者从头编写自己的编译器)。相反,
ClassLoader
s从一开始就存在。