讲解一个java入门的程序,以及其中可能遇到的问题。
首先用记事本编写一个Hello.java的程序,代码如下:
public class Hello{
// private Stringtestprivate="privatetest";
public static voidmain(String args[]){
String version="1.2";
System.out.println("Java Test"+version);
}
}
我把Hello.java放在D盘下的JavaTest目录下,下面打开cmd开始编译和运行程序。
程序没有任何编译错误,编译通过。
接下来运行程序,得到输出:
这是一个最简单的java程序运行,但其中也有一些值得注意的问题,如:
(1) 类名(Hello)必须和文件名(Hello.java)完全一致,否则会报错。
(2) Path必须事先配置指向Jdk下bin目录。
(3) 类当中没有包名,否则必须在编译时:javac 包名/类名.java;运行时:java 包名/类名或者 java 包名.类名。
上面是当你配置一切成功的话,就完成了,那么下面我们就列举一些可能碰到的问题。
1. Javac is not recognized as aninternal or external command,这个时候就去检查你系统的环境变量的path是否设置有问题,指定到对应jdk下的bin目录,一般这个问题很容易解决,添加之后,重新打开一个cmd窗口,敲入命令,没问题。类似的问题都是这样解决,例如javap is not recognized as an internal or external command.(path 用来指定java 命令所在的地方,所以只要出现了java的命令无法识别基本都是path的问题)。
2. 当你编译通过之后,运行的时候出现了java - Could not find or load main class,这个问题的时候,首先考虑你编译通过了,说明你的代码没有编译错误,这个时候错误原因可能有两个。
(1)classpath的问题了,如果你没有设置classpath那么你在你java文件所在的目录进行java不会有任何问题,因为没有classpath环境变量的时候,默认使用当前目录。
我们上面的例子没有指定classpath,所以没有问题。下面我添加一个classpath,内容如下:
我们再次运行java Hello的时候就会出现java - Could not find or load main class,因为我们有classpath这个系统变量,所以会利用这个系统变量定位我们需要的class文件,然而我们的classpath只是指定了两个类库jar文件,并没有指定我们javac编译之后的class文件所存在的文字,那么我们在后面添加D:\JavaTest,如下所示:
再次运行java Hello 就不会报错了。关于classpath三个地方可以设置:
i. 如果没有classpath参数传入,那么默认使用系统的classpath变量;
ii. 如果系统没有默认的classpath,那么默认使用当前目录;
iii. 如果设置了classpath(javac -cp)那么它将覆盖其他地方的值;
(2)你的类里面有package 指定,如package a.b.c; 但是你的Hello.java 却放在test目录下,使用javac只能在当前目录产生class文件,但是运行的时候,却需要在包路径下的class文件,即 a.b.c.Hello.class 这个文件,因此也会抛出上面的问题。最简单的解决办法,把Hello.java 放在 a/b/c目录下,使用即可。
3. 还有一个比较不容易发现的问题,如果你在classpath中设置了多个值,那么你可以在这些设置的路径中都可以运行你的java程序,但是,可能会出现问题。如:我们设置两个classpath,一个是D:\JavaTest和D:\javaclasspath,如下所示:
我们在D:\javaclasspath中也写一个Hello.java 程序代码如下:
public class Hello{
public static voidmain(String args[]){
String version="2.1";
System.out.println("Java Classpath"+version);
}
}
编译通过,但是当你运行的时候,输出的却不是Java Classpath2.1,如下所示
输出的却是Java Test1.2.
解释:
原来我们在classpath中设置了两个地址,并且这两个地址都有一个Hello类,产生了对应的class文件,当你在第二个地址中运行java Hello的时候,需要找到对应的class文件,那么找到的classpath环境变量,第一个值D:\JavaTest里面有Hello.class文件,那么就会使用该文件,从而出现错误。
下面我们删除classpath中D:\JavaTest,
再次编译运行程序,看看结果如下所示:
这次得到了我们想要的结果,因此在实际的程序中要尽量避免这种问题,很不容易发现的问题。
4. 最后一个问题(写的有点累啊!语文不好的程序员真的伤不起),当你在编译指定了classpath的时候可能出现的问题,如我们在test包中有两个文件,一个Hello.java,一个Wai.java。
Wai.java代码如下:
package test;
public classWai{
public static Stringwailai="wailai";
}
Hello.java代码如下:
package test;
public classHello{
public static void main(String args[]){
Stringversion="1.2";
Waiwai=new Wai();
System.out.println("JavaTest"+version+" "+wai.wailai);
}
}
如果我们在Hello.java中要引入第三方的jar包呢?
我们采用
然而程序却编译出错,根据上面的classpath的知识大家猜猜问题在哪?
解释:因为我们设定了-cp参数,就会将classpath系统环境里面的值给覆盖了,或者覆盖了当前目录,那么我们在Hello中引入的Wai类的class在classpath指定的目录下,却不再cp指定的目录下lib/TestJD.jar文件中,因此我们找不到Wai的class类。正确引入方式如下所示
并且我故意敲错几行代码,让大家看看哪些错误会导致哪些问题。
总结一下吧:
1.使用配置好的$CLASSPATH,在编译的时候,如果当前的$CLASSPATH包含了所需要的所有类库,则不需要包含其它的值。只需使用java ***.java,则当前目录下会生成一个***.class,如果在***.java中使用了package a.b.c;但是简单的javac 只能在当前目录生成***.class文件,此时,如果想运行的话,需要在当前目录创建a/b/c/***.class的结构,然后执行java a.b.c.abc
如果此时你使用cd a,进入a目录,则我们需要使用java -cp ../ a.b.c.abc,这样才会找到class文件。
2.Java编译需要使用到其它的jar的时候,则需要指定全部jar路径,不能使用文件夹包含所有形式,使用文件夹class或者普通文件的形式,javac -cp $CLASSPATH:xxx/xxx/xxx.jar:xxx/xxx/xxx.jar xxx.java
3. 在运行的时候,使用java -cpclasspath 的使用方法和javac基本相同,但是需要注意的时候,当我们需要将非$CLASSPATH环境变量包含的值的时候,需要指出当前class所在的位置,这个位置是要考虑package之后的文件夹的位置,例如上面的a/b/c/abc.class,一定要将目录指定到a所在的目录层次。
4.javac:如果当前你要编译的java文件中引用了其它的类(比如说:继承),但该引用类的.class文件不在当前目录下,这种情况下就需要在javac命令后面加上-classpath参数,通过使用以下三种类型的方法来指导编译器在编译的时候去指定的路径下查找引用类。
(1).绝对路径:javac -classpathc:/junit3.8.1/junit.jar Xxx.java
(2).相对路径:javac -classpath../junit3.8.1/Junit.javr Xxx.java
(3).系统变量:javac -classpath%CLASSPATH% Xxx.java (注意:%CLASSPATH%表示使用系统变量CLASSPATH的值进行查找,这里假设Junit.jar的路径就包含在CLASSPATH系统变量中)
(../ 代表当前目录的上一层目录 ./ 代表当前目录)