使用JDK命令行编译、运行Java程序
一般都是通过IDE(如Eclipse、Intellij Idea,MyEclipse)来开发,调试java项目。但作为学习Java初学者,一上来就用这些IDE,可能会被分神,原因是学习IDE的使用也需要相当的付出。应从使用JDK命令行编译、运行Java程序开始,这是学习Java最基本的实验实践技能。
JDK11于2018-09-25正式发布!美国当地时间9月25日,Oracle 官方宣布 Java 11 (18.9 LTS) 正式发布,可在生产环境中使用!这是自 Java 8 后的首个长期支持版本(Long-Term Support),新的长期支持版本每三年发布一次,根据后续的发布计划,下一个长期支持版 Java 17 将于2021年发布。以前的版本,要运行一个 Java 源代码必须先编译(用 javac 命令),再运行(用 java 命令),两步执行动作。而 Java 11 版本中,通过一个 java 命令就直接搞定了,分两步也可以。
JDK(java development Kit,Java 开发工具包),是面向开发人员使用的SDK(软件开发工具包),提供了java的开发环境和运行环境。JRE是java runtime enviroment,是指java的运行环境,是面向java程序的使用者,而不是开发者。
和一般的Windows 程序不同,JDK 安装成功后,不会在“开始”菜单和桌面生成快捷方式。这是因为bin 文件夹下面的可执行程序都不是图形界面的,它们必须在控制台中以命令行方式运行。另外,还需要用户手工配置一些环境变量才能正常使用JDK。
JDK 安装完毕后,在安装路径下有一些文件夹(目录),如:
bin 文件夹:存放编程所要用到的开发工具,包括javac、java等。
lib 文件夹:lib是libarary(类库)的缩写。也就是存放一些程序运行时的依赖文件。
……
关于JDK11的安装与配置,在此跳过,请看他文。
特别说几句,关于书或文章中图示用的截图和操作步骤,这些相对来说是稳定的但决非是固定的。对于初学者,或刚刚接触的技术,好的图示截图和操作步骤可以减少学习过程中出现周折带来的挫折感,但是,我们知道,技术是演化和进步的,改进变革是不可避免的,因此图示截图和操作步骤不可能一成不变,特别是在不同的版本或出现重大升级时有一些显著改变,有时困惑不明,上网又搜索不到,这时自主探索就很重要,所以探索性试验性学习应当发扬。当你练习时发现截图和书或文章中有某些差异时,除作者可能的失误外,应想到你所用的版本、开发环境是否与作者的一致。
可以结合 下列网文学习
Java开发环境搭建与实验教程
Java开发环境搭建与实验教程(适合自学)【2019.10.05修订】_cnds123的专栏-CSDN博客_java开发环境
CMD和PowerShell介绍
CMD和PowerShell介绍_cnds123的专栏-CSDN博客_cmd powershell
在学习本文的过程中,如果遇到疑惑,可以看看上述网文。
本文重点介绍使用JDK11命令行编译、运行Java程序
预备知识:CMD命令入门
按下win键+R键(先按下 键,再按下R键),弹出“运行”窗口,参见下图:
输入cmd 回车(指按下Enter见)或单击“确定”按钮,弹出的cmd命令窗口,参见下图:
输入help 回车,看到一些cmd命令,参见下图:
这里列出了一些命令概述,要想看一个命令的具体用法,你就尝试的在其命令后直接输入/? ,如cd/? 回车
cmd命令不区分大小写,/反斜杠用在命令参数前,\斜杠用在路径中(也可以用/但不提倡)。
下面是常用目录操作
要进入另一个盘输入盘符:回车 如,进入d盘,则输入d:回车
进入子目录就输入cd 子目录名
回到根目录输入cd \
返回上级目录,输入cd..
路径中的“.”代表当前目录;路径中的“..”代表上级目录。
跳转到其他驱动器的其他文件夹,必须加/d参数。否则无法跳转。
带有空格的文件夹(如Documents and settings,Program files等文件夹),给文件夹加引号。 如c:\>cd "documents and settings"
这样的好处是多长的文件名都可以全部显示出来。
使用JDK命令行编译、运行Java程序时,用到这些。
下面开始介绍使用JDK11命令行编译、运行Java程序
javac是编译java文件用的命令,编译之后会生成一个与之前编译的文件一样名字的.class文件, 然后直接用java运行编译之后的.class文件,运行的时候不需要打后缀名。例如,编写一个Test.java文件,使用javac Test.java可以执行编译操作,将生成一个Test.class文件;使用java Test可以执行编写的代码。
如果要编译的.java文件不带完整路径,javac会默认在当前路径中寻找要编译的.java文件。
java命令可以运行class文件字节码。
javac命令可以将java源文件编译成class字节码文件。
java和javac是两个东西前者是jdk版本,后者是java编译器的版本。
用java -version和javac -version得到的结果应一样,如下图:
如此,就可以开始实验了。
【若用java -version和javac -version得到的结果不一样的原因:
系统里边装了2个以上的jdk版本,先查看环境变量path设置,检查是否无效有问题。再搜索java.exe和javac.exe看其位置。与环境变量path设置比较,是否一致。】
特别提示,若系统里边装了2个以上的jdk版本,设置环境变量path,jdk路径靠前的优先。
利用这一点可是实现版本切换。你可以在CMD中输入java –version 回车(指按下Enter键) 看一下当下使用的版本:
在命令行下,大多数java命令可以通过--help参数获得帮助信息。
包括但不仅限于java、javac、javadoc、javap、jdb、javaws、jps、jstat、jstatd等。
例如:
java –help 回车(指按下Enter键)
或者直接输入java命令,不带任何参数:
Java 回车
Javac编译命令和Java运行命令的说明
在cmd中,输入Javac 回车、Java 回车,可以获得这两个命令帮助信息,但是太简略了。因此进一步叙说如下。
javac命令是用来编译.java文件的。常用格式如下:
javac -d destdir srcFile
说明
1、-d destdir 指定存放编译生成的 .class 文件的路径。
若此选项省略,那么默认在当前目录下生成 .class 文件,并且不会生成包文件夹;如 javac JavacTest.java ,便在当前路径下生成了一个JavacTest.class的文件。
若使用-d destdir ,作用(i)在destdir指定的目录中生成class文件,(ii)且,若源代码中含有包语句将按包结构生成对应的目录结构,例如源代码中含有包语句package packA.packB; 将在destdir指定的目录中建立子目录\packA\packB,生成的class文件放到此处。
当前目录可以用“.”来表示,如javac -d . srcFile。【思考:javac -d . srcFile和不写 -d .即javac srcFile效果一样吗?请注意源代码中含有包(package)语句的情况。】
2、srcFile 是要编译的源代码文件名,必须有扩展名,可以带路径:路径\文件名.java,如 D:\TestDir\ Demo.java
3、使用选项 -encoding utf-8 指明源文件的编码格式,如:
javac -encoding utf-8 -d . SoftReferenceTest.java
4、不需要指定目标文件名,编译后以.class为扩展名 以源文件中所定义的类名为其文件名。
5、若Javac编译时提示 某某某使用或覆盖了已过时的 API。比较笼统,可是使用参数-Xlint:deprecation 用来提供详细原因,定位那个语句造成的,类似如下做,将
javac -d D:\JavaTestDir\ch04 D:\JavaTestDir\ch04\DemoA.java,改为
javac -Xlint:deprecation -d D:\JavaTestDir\ch04 D:\JavaTestDir\ch03\ DemoA.java
6、-classpath或-cp参数,设定查找被引用类的位置,可以是目录、jar文件、zip文件(里面都是class文件),jar文件、zip文件需要全路径到jar文件、zip文件。此参数会覆盖掉所有在CLASSPATH 环境变量中的设定。当你要编译的类引用了其它的类,但被引用类的.class文件不在当前目录下时,就需要通过-classpath来引入。
7、-sourcepath参数,指定查找被引用类源文件(.java 文件)的位置,注意不要误认为是指定srcFile的路径。
关于javac命令更多信息参见
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/javac.html
Java命令可以运行class文件字节码。常用格式如下:
Java ClassFile
说明
1、常用选项-classpath ,可简写为-cp,用来指定位置:可以是要运行的类的路径,要运行的类所依赖的其他类的路径、jar文件、zip文件之类,jar文件、zip文件需要全路径到jar文件。它将覆盖CLASSPATH 环境变量中的设定。例如 java -cp c:\dir1\lib.jar Test
2、ClassFile 要运行的类的名,是“纯”名称——不能含路径且不能含扩展名.class。代码中未使用package(包)语句,ClassFile就是类名,若使用了package语句,类名前应带包名,格式为:包名.类名。
程序可以通过编译,但Java命令运行class文件,报“找不到或无法加载主类”错误的原因及处理
有如下两种情况:
1)、可用cmd的cd命令跳转到class文件所在的路径,再运行。javac 编译命令支持带路径的文件名,但java运行命令不支持带路径的文件名而只能是类文件名且不带扩展名,如运行 D:\TestDir\ch03 目录中的DemoA.class 文件,
对此可以这样处理,方法较多:
▲用cmd的cd命令切换到.class 文件所在的目录 cd /d D:\JavaTestDir\ch03,再这样运行java DemoA
▲使用参数 -cp 或 -classpath,可这样执行java -classpath D:\JavaTestDir\ch03 DemoA 或 java -cp D:\JavaTestDir\ch03 DemoA
▲在CLASSPATH环境变量中,加入路径D:\JavaTestDir\ch03,再这样运行java DemoA
▲将.class 文件放到在java命令所在目录下,再这样运行java DemoA ,但一般不用。
2)、若java 源文件使用了package(包)语句,这种情况下使用java命令运行一个.class文件,需要按照package语句指定的包层次转化为的文件路径找到.class文件,因此,用Javac命令来编译.java文件时可以使用-d选项,用来把把编译出的类文件(.class文件)放入包层次对应的目录中,否则需要用户自己来做。这种情况下用Java运行命令中ClassFile的格式为:包名.类名。
关于java命令更多信息参见
https://docs.oracle.com/javase/8/docs/technotes/tools/windows/java.html
以上概述,不太好理解,不要着急,后面实例将具体说明。
下面是编译运行实例:
实例1 一个简单的例子
用记事本编写如下代码
public class CH01_01{
//主要执行区块
public static void main(String[ ] args){
//程序语句
System.out.println("我的第一个Java程序");
}
}
将其保存在 D:\JavaTestDir\ch01文件夹中,文件名CH01_01.java
初学者要注意代码中的英文标点符号,(){} ;,. “ ‘ : / \ = + - < > & % 等等,除在字符串中,应是英文的的,否则导致出错(编译报错)。
如果 Java 程序源代码中定义了 public 类,那么文件名字必须与 public 类名相同,否则会产生编译错误。
【 Java 程序源文件的命名不是随意的,Java文件的命名规则如下(否则会产生编译错误):
1、Java 程序源文件的后缀必须是 .java,不能是其他文件后缀名。
2、如果 Java 程序源代码里定义了一个 public 类,则该源文件的主文件名必须与该 public 类(也就是该类定义使用了 public 关键字修饰)的类名相同,因此,一个 Java 源文件里最多只能定义一个 public 类,并可以包含0个到多个其它(非public 定义的)类。如果 Java 程序源代码里没有定义任何 public 类,那么 Java 程序源程序的主文件名可以是任意的。
根据上面的规则,同时兼顾更好的可读性,通常约定:
(1)一个 Java 源文件推荐只定义一个类,不同的类使用不同的源文件定义。(2)让 Java 源文件的主文件名与该源文件中定义 的 public 类同名。
】
打开CMD
编译(源文件名的扩展名不可缺少)参考下图
javac D:\JavaTestDir\ch01\CH01_01.java (回车,即按下Enter键)
【这时,在D:\JavaTestDir\ch01\产生一个文件CH01_01.class】
用cd命令跳转路径
cd /d D:\JavaTestDir\ch01 (回车,即按下Enter键)
运行
java CH01_01 (回车,即按下Enter键)
显示运行结果
实例2 一个简单的含有package语句的例子
用记事本编写如下代码
package mypack.packA; //package(包)语句
public class CH02_01{
//主要执行区块
public static void main(String[ ] args){
//程序语句
System.out.println("我的第一个Java程序(带包)");
}
}
将其保存在 D:\JavaTestDir\ch02文件夹中,文件名CH02_01.java
我们和实例1一样试试:
编译(源文件名的扩展名不可缺少)参考下图
javac D:\JavaTestDir\ch02\CH02_01.java (回车,即按下Enter键)
【这时,在D:\JavaTestDir\ch02\产生一个文件CH02_01.class】
用cd命令跳转路径
cd /d D:\JavaTestDir\ch02 (回车,即按下Enter键)
运行
java CH02_01 (回车,即按下Enter键)
报错
为什么?这是因为java执行class文件对包(package)的路径是强依赖的,有两种解决办法:
(1)在class文件(本例是CH02_01.class)所在的目录中,按包的结构在新建一个包名一样的子目录,将CH02_01.class移动过去,再用java命令运行。本例子中包名mypack.packA,所以在D:\JavaTestDir\ch02中建立先建立子目录mypack,再在mypack中建立子目录packA,参见下图:
然后,用cd /d D:\JavaTestDir\ch02(回车,即按下Enter键)跳转路径 ,用java mypack.packA.CH02_01 (回车,即按下Enter键)提示:类名前含包名
显示运行结果。参见下图:
(2)编译时使用-d选项。javac 的-d选项用于指定生成的class目标文件的目录。如果某个类是一个包的组成部分,则 javac 将把该类文件放入反映包名的子目录中,必要时自动补建目录。
编译
javac -d D:\JavaTestDir\ch02 D:\JavaTestDir\ch02\CH02_01.java
用cd命令跳转路径
cd /d D:\JavaTestDir\ch02\ (回车,即按下Enter键)
用java mypack.packA.CH02_01 (回车,即按下Enter键)提示:类名前含包名
显示运行结果。参见下图:
相比较(1)法比较麻烦,推荐(2)。
小结,在源文件里指定了package (包)语句,命令行编译、运行Java程序时注意事项:
源文件中有包声明语句时,编译要使用“-d 路径”参数,表示编译时自动生成与包同名的文件夹,并把类文件放到该文件夹下,目的是运行时让JVM能够在包文件夹下找到要加载的类文件。运行一个类需要带包名。使用了package语句的源码编译(用javac命令)的时候用文件名,但是执行(用java命令)的时候肯定是需要带包名的文件名。参见上面的例子。
【Java 的package (包)语句
语法格式为:
package pkg1[.pkg2[.pkg3…]];
程序中如果有package语句,该语句一定是源文件中的第一条可执行语句,它的前面只能有注释或空行。另外,一个文件中最多只能有一条package语句。
包的作用:
1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。
例、一个Something.java 文件它的内容
package net.java.util;
public class Something{
...
}
那么它的路径应该是 net/java/util/Something.java 这样保存的。
关于Java 包(package)更多只是参见
】
简单Java程序的一般不用package (包)语句。
实例3 一个图形界面的例子
用记事本编写如下代码
import java.awt.FlowLayout;
import javax.swing.*;
public class DemoA {
public static void main(String[] args) {
JFrame jf = new JFrame("测试窗口2");
jf.setSize(300, 300);
jf.setLayout(new FlowLayout());
jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jf.setVisible(true);
}
}
将其保存在 D:\JavaTestDir\ch03文件夹中,文件名DemoA.java
编译 参考下图
javac -d D:\JavaTestDir\ch03 D:\JavaTestDir\ch03\DemoA.java(回车,即按下Enter键)
【或
javac D:\JavaTestDir\ch03\DemoA.java (回车,即按下Enter键)
这时,在D:\JavaTestDir\ch03\产生一个文件DemoA.class】
用cd命令跳转路径
cd /d D:\JavaTestDir\ch03 (回车,即按下Enter键)
运行
java DemoA (回车,即按下Enter键)
显示运行结果
上面的例子虽然简单,但对问题情况的说明足够了。初学者有了这些实践经验,应该能减少学习过程中的很多挫折感。
实例4 一个稍复杂的例子,由两个源文件组成User.java和Hello2.java,Hello2.java引用了另一个User.java中的类
第一个源文件User.java,保存在D:\JavaTestDir\ch04目录中
package com.andy.model; // package(包)语句
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
第一个源文件Hello2.java,保存在D:\JavaTestDir\ch04目录中
package com.andy; // package(包)语句
import com.andy.model.User;
public class Hello2 {
public static void main(String[] args) {
User user = new User();
user.setId(1);
user.setName("andy1");
System.out.println(user);
}
}
这个源文件中含有main方法,这是Java程序执行时的入口。
有了前3个实例的编译运行实践,实例4 的编译运行将着重要点说明。
先编译User.java
javac -d D:\AA1234 D:\JavaTestDir\ch04\User.java
【-d D:\AA1234,指定编译结果存放位置】
再编译\Hello2.java
javac -d D:\JavaTestDir\ch04 D:\JavaTestDir\ch04\Hello2.java ,编译失败
因为找不到放在D:\AA1234引用类
应当这样
javac -classpath D:\AA1234 -d D:\JavaTestDir\ch04 D:\JavaTestDir\ch04\Hello2.java
【-classpath D:\AA1234指定引用文件的位置】
现在可以运行了
java -classpath D:\AA1234;D:\JavaTestDir\ch04 com.andy.Hello2
【-classpath D:\AA1234;D:\JavaTestDir\ch04 其中D:\AA1234和D:\JavaTestDir\ch04缺一不可,两者之间用分号分割】
运行结果:
com.andy.model.User@9e89d68
在命令中使用-classpath的设置,也可以通过环境变量CLASSPATH设置,但这比环境变量CLASSPATH中设置灵活方便。