Java命令行运行错误: 找不到或无法加载主类 | 您所在的位置:网站首页 › 载入程序时出错怎么办 › Java命令行运行错误: 找不到或无法加载主类 |
前言:虽然学习Java语言约有两年多,但在最近需要使用命令行工具编译并运行Java程序时,还是报错了。花费了一些时间,解决了该问题,发现解决方法在初学Java时使用过。一则,为了避免以后再出现同样的问题而浪费不必要的时间;二则,作为使用该语言的程序员,对于该语言的一些基本问题,应该有清晰的理解和认识;三则,网上的一些解决方案,不够完备。有的没有解释问题原因,直接给出答案;有的,未列举出某些常见情况的解决方案。因此,写此文章,让读者可以举一反三,深入理解问题。 一、 问题分析找不到或无法加载主类,主要原因有两个: 1. 类名错误 2. 类所在位置未添加至类加载路径中 二、 问题解决本部分将针对在“一”中提出的两个问题发生原因,分别进行分析及处理。并且会介绍java的一些和处理问题相关的基本概念。 1. 类名错误全限定类名:包名+类名。另外,当包名为空时(即代码不包含package语句),称类所在包为默认包 例如,以下代码的全限定类名为:“com.gzn.demo.HelloWorld” // 文件名HelloWorld.java package com.gzn.demo; public class HelloWorld { public static void main(String args[]) { System.out.println("hello world"); } }在运行java程序时,全限定类名可以唯一确定该文件,就像是文件系统中路径(相当包名)+文件名(相当类名)可以唯一确定一个文件一样。本质上包名发挥的作用和文件系统中的目录相同,有利于文件分隔避免重名。 现在存在一个问题,Java是如何识别一个类文件的包名的? 实际上,包名的识别是通过文件系统的目录实现的 。例如,上文提到的包名为“com.gzn.demo”的HelloWorld.java文件,该文件在文件系统中的位置为 “com\gzn\demo”,编译后的HelloWorld.class也在"com\gzn\demo"目录下,因此,在运行java程序后加载类时,只需在“com\gzn\demo”目录下,查看是否存在要查找的文件即可。简而言之,目录(或路径)名于包名存在一一映射的关系,可认为相等。 在Windows操作系统的命令行下,运行Java代码的语法格式为,注意,此时java命令位于目录com的上一级目录(一般为项目的目录名);类名不能包含扩展名.class: Java 全限定类名 例如java com.gzn.demo.HelloWorld;包名为空则为java HelloWorld Windows操作系统中还有另一种语法格式(其他系统未必可以),不常用,使用反斜杠代替了点好,之所以没用正斜杠,个人猜测是为了和系统的文件分隔符进行区分: 例如Java com/gzn/demo/HelloWorld; 包名为空则为java HelloWorld 可能出错情况一 :在命令行运行java程序时,类名包含了扩展名 在helloworld项目目录下运行java命令,HelloWorld.class文件在“com\gzn\demo”目录下,即包名为com.gzn.demo,上文已介绍,不在赘述。 C:\Users\gzn\helloworld>java com.gzn.demo.HelloWorld.class 或者包名为空 C:\Users\gzn\helloworld> java HelloWorld.class 上述写法,会出现报错,原因是它不符号java运行程序的语法格式,java可能把“HelloWorld.class”作为一个整体类名处理,那么要查找的文件可能是“HelloWorld.class.class”,显然是找不到的。 可能出错情况二 :运行Java命令时未指明全限定类名的包名部分或指明了包名但Java命令运行的位置不正确 假设HelloWorld.class,包名为com.gzn.demo,所在位置为: C:\Users\gzn\helloworld\com\gzn\demo 运行以下命令 C:\Users\gzn\helloworld\com\gzn\demo>java HelloWorld 运行命令后,会在当前目录下,查找并读取该文件后,发现该类为“com.gzn.demo.HelloWorld”(全限定类名唯一确定一个类,上文已介绍)与我要运行的类“HelloWorld”并不是同一类,因此,找不到要运行的类。 于是,很自然的一个想法是运行以下命令 C:\Users\gzn\helloworld\com\gzn\demo>java com.gzn.demo.HelloWorld 包名和文件名是一一映射的(上文已介绍),运行命令后,会从命令所在位置开始(即以命令所在位置为相对路径),查找“com\gzn\demo\”路径下的HelloWorld文件。由于“C:\Users\gzn\helloworld\com\gzn\demo”路径下根本不存在目录“com”(更不用说gzn\demo),因此,找不到运行的类。 正确的运行命令的方法,呼之欲出,只需改变命令的运行位置即可,如下所示 C:\Users\gzn\helloworld>java com.gzn.demo.HelloWorld 运行命令后,会在“com\gzn\demo”路径下找到并读取HelloWorld文件,发现该类的全限定名为“com.gzn.demo.HelloWorld”,查找的类正是Java想要运行的类。 以上是比较初级的出错情况,下文将要介绍相对比较高级的出错情况,这也是其他博文未曾给出解决方案的情况。同时还会介绍classpath的概念,及使用方法。加油! 2. 类所在位置未添加至类加载路径中类加载路径(Classpath):当你的程序依赖第三方或者自己写的类文件时,需要指出上述文件的所在位置,即类加载路径。Java虚拟机的类加载器会在你指定的路径中,查找你的程序所依赖的类文件(依赖的类文件 在import语句中指定) classpath可以通过以下两种方式指定: 方式一:配置环境变量这种方式是初学Java者肯定了解的方式,通常在下载完JDK后就会进行配置。然而在JDK1.5之后,官方已不建议使用这种方式来指定类加载路径,原因后文扩展部分会谈及。
这种方式是JDK1.5后官方建议的方式。当你在命令行下运行java命令时,如果没有指定-classpath参数,那么默认使用环境变量中设置的ClASSPATH。官方建议,你在运行每个程序时,为其显示设置所依赖的类文件所在的位置,而不是使用“全局”性质的环境变量中CLASSPATH。一旦你运行程序时指定了-classpath参数,环境变量中的CLASSPATH就不会在使用,而是使用你参数的classpath。实际上,JDK1.5以后,官方已经不建议配置CLASSPATH环境变量。 语法格式如下: java -cp 全限定类名 路径:依赖的文件所在的绝对路径(或相对路径),如果类文件在jar包中,路径后还要写上jar包的名字,例如“C:\users\gzn\mylib\algs4.jar” 注意,“.”代表当前路径,即java命令运行时所在路径。 可能出错情况三 :存在依赖外部jar包时,命令行运行java命令,classpath参数中只是添加了外部jar包路径,没有添加当前目录“.”,导致要运行的类文件找不到。 或者,程序在IDE(eclipse、IDEA等)开发工具中可以运行,但是在命令行下不能运行,情况相同。 在某篇高赞博文中,依然存在的问题 public class StdOut public static void print(String s); 打印输出指定的字符串 HelloWorld.java package com.gzn.demo; import edu.princeton.cs.algs4.StdOut; |
CopyRight 2018-2019 实验室设备网 版权所有 |