执行javac命令时是如何查找java文件去编译的
观点1
javac命令后面直接跟java文件时,先执行被执行的java文件,再根据该java文件里面引用到的类去查找其他java文件。
验证案例1
目录
Student.java文件内容
package people;
public class Student {
private String name;
private Integer age;
public Student(){
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
Main.java文件内容
import people.Student;
public class Main {
public static void main(String[] args) {
Student student = new Student("王路飞", 19);
System.out.println(student.getName() + "今年" + student.getAge() + "岁");
}
}
在demo01目录中执行编译命令
javac Main.java
编译成功编译结果如下
验证结果:猜测成立
验证案例2
假设我们创建一个目录main,把Main.java文件放进去,如下
进入main目录,执行编译命令
javac Main.java
编译结果报错找不到Student类,如下
原因分析:根据我们的猜测,javac命令执行时是在当前目录下找到Main.java文件进行编译,然后通过导入的类路径people.Student,去people目录找Student文件。但是当前main中并没有people包,所以就找不到这个Student.java文件
验证结果:猜测成立
验证案例3
还是使用案例2中的目录结构和文件,但是这次我们不在main目录中执行编译命令,而是在demo02中执行
执行命令如下
javac ./main/Main.java
执行结果如下
原因分析:javac是在demo02目录下执行的,并指定了./main/Main.java文件进行编译。当Main需要用到people下的Student.java文件时,就在执行命令的当前目录下查找peeple中的Student.java文件,所以能找到,所以能顺利编译。
验证结果:猜测成立
观点2
执行javac的时候,如果想要从其他目录找到需要编译的文件,那么需要加参数-cp指定目录
验证案例1
还是拿观点1中验证案例2进行实验
目录结构如下
进入main目录执行一下命令
javac -cp ..: Main.java
注:-cp参数后面如果是多个路径的话需要:或者;隔开,具体用哪个需要根据系统来选定window系统用、os系统用:
执行结果如下
执行成功
原因分析:该案例编译的时候除了可以在main中查找需要编译的文件,也会在指定的目录也就是main的上层目录demo02中查找需要编译的文件,demo02有需要找到的目录和文件,所以编译成功
总结
javac命令查找需要编译的文件过程如下
1、先找到主程序进行编译,然后根据主程序导入对类的全路径在当前目录去查找需要编译的的文件
命令如下
javac Main.java
2、如果相关联的文件不在当前目录,可以通过-cp参数指定,多个路径情况用:或者;分开
命令如下
java -cp ..: Main.java
执行java命令时是如何查找class文件的
观点1
在使用java命令执行程序时,会先在当前目录根据全限定类名去找到对应目录的class,再根据class中引用的包名和类名去相应的目录查找被依赖的class文件
验证案例1
那上面编译完的demo01来执行,目录如下
在demo01目录执行java命令
java Main
执行结果
验证结果:猜测正确
验证案例2
将上面的案例目录做个调整,创建main目录,然后将Main.class移动到main目录,在main目录执行命令
目录结构
进入main目录执行命令
java Main
执行结果如下
错误原因分析:在main中执行命令,由于当前目录下根据包名people.Student,找不到对应的目录和类所以找不到
验证结果:观点成立
观点2
java 命令可以通过-cp的方式去指定类路径
验证案例1
还是使用上面的目录结构,进入main目录执行如下命令
java -cp ..: Main
执行结果
验证结果:观点成立
引入jar包的情况下,应该如何处理
观点1
引入jar包的情况下,只需要把jar包设置成类路径即可
验证案例1
创建目录结构如下,在lib中引入jar包,并在Main.java中调用jar中的功能
Main.java内容如下
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
/**
* @Author ${USER}
* @Date ${DATE} ${TIME}
*/
public class Main {
public static void main(String[] args) {
DateTime date = DateUtil.date();
System.out.println(date);
}
}
我们将jar包的路径当初类路径处理我们应该执行命令如下
javac -cp lib/hutool-all-4.6.2.jar: Main.java
注意:如果是用window系统-cp后面的路径之间应该用;隔开
执行结果
执行成功,验证成功,观点成立
指定编译后class打存放位置
使用demo02,进行测试,在demo02目录中新建target目录,目录结构如下
执行命令
javac -d target main/Main.java
执行结果
进入target目录,运行
java Main.class
执行结果
java如何打jar包,使用jar命令打jar包
创建文件夹demo04,总体结构目录如下
Main.java文件
import people.Student;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
public class Main {
public static void main(String[] args) {
Student student = new Student("王路飞", 19);
System.out.println(student.getName() + "今年" + student.getAge() + "岁");
DateTime date = DateUtil.date();
System.out.println(date);
}
}
Student.java文件
package people;
public class Student {
private String name;
private Integer age;
public Student(){
}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
编译
javac -cp lib/hutool-all-4.6.2.java: -d target Main.java
执行后target目录如下
复制文件夹lib到target下
尝试运行:
java -cp lib/hutool-all-4.6.2.jar: Main
执行结果
王路飞今年19岁
2023-09-22 00:14:16
开始打包
新建目录META-INF,在里面创建文件MENIFEST.MF
文件内容如下
Manifest-Version: 1.0
Class-Path: lib/hutool-all-4.6.2.jar
Main-Class: Main
Class-Path填jar包路径,多个用空格隔开
Main-Class填主类全类名
执行打包命令
jar -cvfm Main.jar META-INF/MENIFEST.MF lib people Main.class
命令说明 c表示创建一个jar包,v表示创建过程中打印信息,f表示包名,m表示元数据文件目录(也就是MENIFEST.MF路径)
该案例jar包名出是Main.jar , 需要被打包的文件是lib people Main.class ,多个文件间用空格隔开
打包结果
运行jar包
java -jar Main.jar
运行结果
王路飞今年19岁
2023-09-22 00:27:20
运行成功
总结
1、打jar包需要创建META-INF/MENIFEST.MF文件,并要填jar包类路径和主程序全类名
2、使用以下命令打包
jar -cvfm Main.jar META-INF/MENIFEST.MF lib people Main.class
命令说明 c表示创建一个jar包,v表示创建过程中打印信息,f表示包名,m表示元数据文件目录(也就是MENIFEST.MF路径)
该案例jar包名出是Main.jar , 需要被打包的文件是lib people Main.class ,多个文件间用空格隔开