在使用命令行进行java程序的编译和运行时,报“ 找不到或无法加载主类”的错误。
首先,在ide中是可以正常编译和运行的。查找了部分的解决方案,很多人提供的思路是环境变量设置有误,但检查
环境变量等均无问题,在参阅了文章:
http://www.cnblogs.com/wangxiaoha/p/6293340.html
之后,发现产生错误的原因是对package,类路径以及java编译器及虚拟机查找文件的模式不理解,以至命令行输入混乱。进而查阅书籍,在《Java核心技术卷1》中对Windows系统下使用命令行运行java程序,类路径以及包之间的关系有较为详细的阐述,总体来说有一下几点需要注意。
1.编译器在编译源文件的时候不检查目录结构。但是如果包和目录不匹配,虚拟机就找不到类。
所以在出现问题后,发现编译总能通过,但是运行时会报错。
2.编译器对文件进行操作,而java解释器加载类
eg:javac com/mycompany/PayrollApp.java
java com.mycompany.PayrollApp
Oracle官方也提出了初学者易犯的错误就包括使用java xx.class的形式运行程序
A common mistake made by beginner programmers is to try and run the java
launcher on the .class
file that was created by the compiler. For example, you'll get this error if you try to run your program with java HelloWorldApp.class
instead of java HelloWorldApp
. Remember, the argument is the name of the class that you want to use, not the filename.
3.javac编译器总是在当前目录查找文件,但是Java虚拟机尽在类路径中有"."目录的时候才看当前目录。如果没有设置类路径也不会有什么问题,默认的类路径包含"."目录,然而设置了类路径却忘记包含"."目录,程序任可通过编译但是无法运行。
第三条是导致今天发现的错误的直接原因
当我们没有在程序中定义package的时候,直接在文件目录下进行编译和运行并不会出现问题
当我们加上package后
我们可以通过编译但是无法运行,这就是类路径与目录不匹配造成。
按照第三条中的描述,添加了"."的包,让解释器在demo目录下搜索文件,问题解决。
转自:https://www.cnblogs.com/wangxiaoha/p/6293340.html
其实原因很简单,我们忽略了2个细节。
1.java指令默认在寻找class文件的地址是通过CLASSPATH环境变量中指定的目录中寻找的。
2.我们忽略了package的影响。
第一个问题好解决:
我们直接在CLASSPATH环境变量中加入“.;”即可。“.”的意思是搜索当前目录
第二个问题看下面分析:
看下面两个类
类A和类B的唯一差别就是没有定义包名。
我们的工程路径是D:\HelloWorld,在HelloWorld文件夹中建立一个src文件夹,类B的源代码文件就放在src中。用javac编译完以后
会在src文件夹中生成NewsManager.class,如下
为什么加入了package后就不对了呢?
类A中package的路径是org.will.app.main。按照java规定,我们应该按照package定义的路径来存放源文件,类A应该放入:
src\org\will\app\main下,如下:
成功!
总结:
一、java执行class文件是根据CLASSPATH指定的地方来找,不是我们理解当前目录。如果希望它查询当前目录,需要在CLASSPATH中加入“.;”,代表当前目录。
二、java执行class文件对package的路径是强依赖的。它在执行的时候会严格以当前用户路径为基础,按照package指定的包路径转化为文件路径去搜索class文件。各位同学以后注意就OK啦。至于网上说的要在CLASSPATH要加各种包等等都是泛泛而谈,真正静下心分析这个问题的资料不多。很多都没有说到点子上,会误导人的。