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

为什么javac后加.java,java后不加.class?的更多相关文章

  1. java 安装后 不能 java javac 说找不到命令 -bash: javac: command not found

    java 安装后 不能 java javac  说找不到命令 -bash: javac: command not found 不是环境变量的问题, 直接cd到java的目录 也不能执行命令 后来发现是 ...

  2. servlet中Java连接数据库后的基本操作

    servlet中Java连接数据库后的基本操作 在eclipse中新建一个工程:login 在Server中新建一个服务器,基本的操作不用说了,在前两天的笔记中可以找到; 需要知道数据库的用户名和密码 ...

  3. 第5篇-调用Java方法后弹出栈帧及处理返回结果

    在前一篇 第4篇-JVM终于开始调用Java主类的main()方法啦 介绍了通过callq调用entry point,不过我们并没有看完generate_call_stub()函数的实现.接下来在ge ...

  4. java编译后字节码解析

    java编译后字节码解析 参考网摘: https://my.oschina.net/indestiny/blog/194260

  5. 从事三年java开发后, 我打算转人工智能

    作为一个2015年参加java培训,2016年计算机科学与技术本科毕业后一直从事java开发的程序员来说, 做出这一步真的不容易, 可是我没赶上java最火的时候,反而渐渐感受到了java的没落, 目 ...

  6. Java编译后产生class文件的命名规则

    今天刚好有同学问了下Java编译后产生的.class文件名的问题,虽然一直都在使用Java做开发,但是之前对编译后产生的.class文件名的规范也基本没做了解过,也真的是忏愧啊!今天无论如何都要总结下 ...

  7. (转)Java编译后产生class文件的命名规则

      今天刚好有同学问了下Java编译后产生的.class文件名的问题,虽然一直都在使用Java做开发,但是之前对编译后产生的.class文件名的规范也基本没做了解过,也真的是忏愧啊!今天无论如何都要总 ...

  8. NBU For Windows 更新后无法启动Java Console

    系统环境:Win Server 2016 备份软件:NBU 8.1   Case :Windows系统默认自动安装系统补丁,重启过程中自动进行了Update,打上了最新的补丁后,NBU Java Co ...

  9. Rsa加解密Java、C#、php通用代码 密钥转换工具

    之前发了一篇"TripleDes的加解密Java.C#.php通用代码",后面又有项目用到了Rsa加解密,还是在不同系统之间进行交互,Rsa在不同语言的密钥格式不一样,所以过程中主 ...

  10. 监听spring加载完成后事件

    有这个想法是在很早以前了,那时的我没有接触什么缓存技术,只知道hibernate有个二级缓存.没有用过memcache,也没有使用过redis. 只懂得将数据放到数组里或者集合里,一直不去销毁它(只有 ...

随机推荐

  1. pillow 创建图片并添加一些自定义信息

    from PIL import Image vm = Image.new('RGBA', (dshape[1], dshape[0])) vm = Image.fromarray(np.array(s ...

  2. libnode使用addon

    自己编译的一个libnode.so后,在js里调用hello.node的 addon时候会报错. Error: dlopen failed: cannot locate symbol "na ...

  3. 操作系统实战45讲笔记- 05 CPU工作模式:程序执行的三种模式

    实模式 实模式又称实地址模式,实,即真实,这个真实分为两个方面,一个方面是运行真实的指令,对指令的动作不作区分,直接执行指令的真实功能,另一方面是发往内存的地址是真实的,对任何地址不加限制地发往内存. ...

  4. C# Winform 多线程更新界面UI控件,解决界面卡顿问题(转)

    前言 多线程刷新界面主要用到多线程,委托,线程安全.事件等一系列高难度的C#操作. 1.使用timer控件对要刷新的控件进行定时刷新 对刷新频率要求不高的时候,可以使用该方法. 2.刷新UI控件 在开 ...

  5. 攻防世界-file_include(绕过base64)

    有简单过滤防护的文件包含  一.源码分析 易知$filename处可能会存在文件包含漏洞.但注意到include了一个./check.php文件,猜测可能有过滤.先不管,于是直接使用普通payload ...

  6. js 浮点数加、减、乘、除。

    1.浮点数加法运算 function numAdd(arg1, arg2) { var r1, r2, m; try { r1 = arg1.toString().split("." ...

  7. 解决pycharm中cv2报错问题,anaconda安装opencv

    写在前面的话:cv2 报错是因为没安装opencv安装包所导致,并且在pycharm终端不可使用pip install cv2 进行安装! 如何解决cv2报错: 首先,值得注意的是在pycharm中, ...

  8. C#中检测代码执行时间

    使用System.Diagnostics.Stopwatch, using System; using System.Diagnostics; using System.Threading; clas ...

  9. liunx查看端口使用情况

    netstat -ntlp //查看当前所有tcp端口

  10. Finance财务软件(月度结转专题)

    支持按模板结转 默认结转模板 1.结转收入 借: 6001 主营业务收入 6051 其他业务收入 6301 营业外收入 贷: 4103 本年利润 2.结转成本.费用和税金 借: 4103 本年利润 贷 ...