为什么javac后加.java,java后不加.class?

Javac和java命令的用法:javac需要文件,Java需要执行类或jar文件
javac用法:

 

java用法

 

例子

 Java命令后的“test.Test.class”会被认为是包含main方法的主类,但是JVM去加载该类时找不到该类。

 

有如下的一些解释:

  • 编译时,添加后缀表示把一个文件(即扩展名为Java的文件)转换为字节码,之后,运行时,运行的不是文件,而是文件的类名称,因为主类和类名保持一致,所以你运行输入的Test是类名,而不是扩展名;
  • 《深入理解Java虚拟机》第六章图示6-1中各种可以编译为class字节码的语言都有对应的编译器,编译Java程序的编译器为javac编译器,即为Java compiler的简称.

 

 

疑问:

既然javac是编译Java程序的编译器,它的输入一定是.java文件,为什么不把后缀名去掉?
javac命令和Java命令一个带后缀名一个不带后缀名是为什么?

多种文件均可以编译为class字节码,每种语言都有不同的后缀名和对应的编译器,但是为什么编译器不省略掉后缀名?难道javac编译器还可以编译其他后缀名的文件?
如果从另一方面看,带上后缀名是正常操作,那么问题就是Java命令为什么去掉了.class后缀?
这和Java虚拟机的规范有关,class文件是Java虚拟机执行引擎的数据入口,所有的Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果。Java命令后为类名或jar文件,即它有.class、.jar形式。

 

stackoverflow上找到一个解释如下:
https://stackoverflow.com/questions/8651140/why-compiler-needs-java-suffix-but-interpreter-doesnt-need-class-suffix

 

As a couple of other answers have explained, the Java compiler takes a file name as an argument, whereas the interpreter takes a class name.

So you give the .java extension to the compiler because it's part of the file name, but you don't give it to the interpreter because it's not part of the class name.

But then, you might wonder, why didn't they just design the Java interpreter differently so that it would take a file name? The answer to that is that classes are not always loaded from .class files. Sometimes they come from JAR archives, sometimes they come from the internet, sometimes they are constructed on the fly by a program, and so on. A class could come from any source that can provide the binary data needed to define it. Perhaps the same class could have different implementations from different sources, for example a program might try to load the most up-to-date version of some class from a URL, but would fall back to a local file if that failed. The designers of Java thought it best that when you're trying to run a program, you don't have to worry about having to track down the source that defines the class you're running. You just give the fully qualified class name and let Java (or rather, its ClassLoaders) do the hard work of finding it.

正如其他几个答案所解释的那样,Java 编译器采用文件名作为参数,而解释器采用类名。因此,您将 .java 扩展名提供给编译器,因为它是文件名的一部分,但您没有将其提供给解释器,因为它不是类名的一部分。
但是,您可能想知道,为什么他们不设计不同的 Java 解释器,以便它采用文件名?答案是类并不总是从 .class 文件加载。有时它们来自 JAR 包,有时它们来自互联网,有时它们是由程序动态构建的,等等一个类可以来自任何可以提供定义它所需的二进制数据的来源。也许同一个类可能有来自不同来源的不同实现,例如,程序可能会尝试从 URL 加载某个类的最新版本,但如果失败,则会回退到本地文件。 Java 的设计者认为,当您尝试运行程序时,最好不必担心必须追踪定义您正在运行的类的源代码。您只需给出完全限定的类名,然后让 Java(或者更确切地说,它的 ClassLoader)来完成查找它的艰苦工作。

 

此外JDK的javac命令是字节码生成技术的“老祖宗”,并且javac也是一个由Java语言写成的程序,它的代码存放在OpenJDKde langtools/src/share/classes/com/sun/tools/javac目录中。

http://hg.openjdk.java.net/jdk8u/jdk8u60/langtools/file/b9abf5c3d057/src/share/classes/com/sun/tools/javac

 

posted @ 2021-07-18 12:24  dedication  阅读(952)  评论(0编辑  收藏  举报