4.6类路径

4.6.1什么是类路径

前面我们讨论过包,知道字节码文件最终都会被放到和包名相匹配的树状结构子目录中。例如上一节的例子:

  其实类还有一种存放方式,就是可以归档到一个jar文件中,jar文件其实就是把字节码文件连同子目录一同归档到一个压缩文件中。jar文件是使用zip格式压缩的,我们可以使用zip程序来查看和解压jar文件。其实Java自带的类库就是jar文件。例如JRE安装目录jre/lib和jre/lib/ext下就有很多jar。我们看一下jre/lib/rt.jar的结构:

我们看到,无论是单独存放还是归档jar,都有一个基目录(黑色部分),上面2个图的基目录分别为:

D:\Java大失叔\workspace\BaseJava\bin

C:\Program Files\Java\jre1.8.0_261\lib

我们采用基目录+包树状结构,就可以定位到某个类,例如:

D:\Java大失叔\workspace\BaseJava\bin\com\javadss\javase\ch04\PackageTest.class

C:\Program Files\Java\jre1.8.0_261\lib\java\lang\System.class

这里的基目录,就是类路径,英文叫classpath。类路径就是java编译器或JVM用来定位类的基目录,类路径可以有多个,是一组路径的集合。无论是编译还是运行,都需要设置类路径,类路径的形式和操作系统相关。

在Windows环境下,采用分号(;)分隔,如果路径中含有空格,需要用引号(“”)括起来,形式如下:

D:\Java大失叔\workspace\BaseJava\bin; “C:\Program Files\Java\jre1.8.0_261\lib”;

在Linux环境下,采用冒号(:)分隔,形式如下:

usr/local/bin:usr/dss/java/bin

4.6.2编译

  我们假设有3个类:A、B、C。main方法在C中,C中访问了A和B,同时还访问了java.lang.System类。它们的结构如下:

其中A和B是空类,C类的代码如下:

package com.javadss.javase.ch04.ccc;  

import com.javadss.javase.ch04.aaa.A;
import com.javadss.javase.ch04.bbb.B; public class C {
public static void main(String[] args) {
A a = new A();
B b = new B();
System.out.println("classpath");
}
}

现在我们用命令行来编译A、B、C,还记得编译命令吗?编译命令如下:

javac -d 编译后class的路径 源文件

则编译命令如下:

javac -d D:\Java大失叔\workspace\BaseJava\bin D:\Java大失叔\workspace\BaseJava\src\com\javadss\javase\ch04\aaa\A.java

javac -d D:\Java大失叔\workspace\BaseJava\bin D:\Java大失叔\workspace\BaseJava\src\com\javadss\javase\ch04\bbb\B.java

javac -d D:\Java大失叔\workspace\BaseJava\bin D:\Java大失叔\workspace\BaseJava\src\com\javadss\javase\ch04\ccc\C.java

编译A、B的时候没有问题,但是编译C的时候,遇到了问题,报错:

这是因为C类中引用了A和B,但是编译命令中没有指定A和B的绝对路径,因此会报错“程序包不存在”、“找不到符号”这些错误。我们可以在命令行中增加-classpath或-cp选项,设置A和B的类路径,设置后的命令如下:

javac -cp D:\Java大失叔\workspace\BaseJava\bin -d D:\Java大失叔\workspace\BaseJava\bin D:\Java大失叔\workspace\BaseJava\src\com\javadss\javase\ch04\ccc\C.java

再次执行,编译成功。有的同学可能要问了,C中也引用了java.lang.System类,为什么不用设置System类的类路径呢?这是因为System属于JDK的类库,javac编译时,会默认搜寻JDK的类路径。

当我们的程序引用了很多类,这些类分散在不同的地方,就需要把所有的类路径都写到命令行中,比如类路径为:

D:\Java大失叔\workspace\BaseJava\bin;.;“C:\Program Files\Java\jre1.8.0_261\lib”;

注意,中间有一个“.”,这个表示当前目录。当我们这样写的时候会导致命令行非常长,我们可以用设置环境变量classpath的方式来减少命令行的长度,设置环境变量的具体形式和操作系统有关,Windows命令格式如下:

set classpath=类路径集合

例如:

set classpath= D:\Java大失叔\workspace\BaseJava\bin; “C:\Program Files\Java\jre1.8.0_261\lib”;

我们在命令行窗口中执行上述命令后,在窗口关闭之前,所有的编译命令都不需要用-cp选项来设置类路径了。网上有很多网文或教程中,都喜欢在系统环境变量中设置classpath,这是笔者不推荐的。推荐的几种做法是

  1. 在命令行中用-classpath或-cp选项
  2. 在命令行中设置classpath环境变量
  3. 编写shell脚本,将设置classpath环境变量和编译命令一起写入脚本

事实上,编译器会按照下面方式搜寻类:

  • 从JDK的类库中搜寻
  • 从当前目录下搜寻
  • 从classpath环境变量中搜寻
  • 从classpath选项中搜寻

如果搜寻类的时候发现了一个以上的同一个类,就会产生编译错误。

  另外,编译器还会做很多其他工作,例如编译器在搜寻类的时候,还会查看源文件,如果发现被引用的类的源文件比类文件新,还会自动的重新编译源文件。

4.6.3运行

用命令行运行程序和编译类似,我们也需要用-classpath或-cp选项指定类路径,常用的命令格式为:

java -classpath 类路径 包含main方法的类的完整类名

我们来运行上面的例子C类,则命令行如下:

javac -cp D:\Java大失叔\workspace\BaseJava\bin com.javadss.javase.ch04.ccc.C

同样,对于JDK的核心类库,我们不需要显示的加到类路径中。当然,我们也可以用设置classpath环境变量的方法预先设置,然后执行运行命令的时候可以不用加上-classpath选项了。

这里需要注意一点,对于编译器来说,总是会搜寻当前目录(换句话说,会默认把当前目录加入到类路径),但是虚拟机JVM仅仅在不设置classpath环境变量,也不加-classpath或-cp选项的时候,才会把当前目录加入到类路径中。

《Java从入门到失业》第四章:类和对象(4.6):类路径的更多相关文章

  1. 《Java从入门到失业》第二章:Java环境(四):IDE集成环境

    2.4IDE集成环境 在掌握了编写.编译和运行Java程序的基本步骤以后,你肯定就在想,这太麻烦了,有没有更好的工具?当然有了,那就是IDE.IDE就是专业的集成开发环境(Integrated Dev ...

  2. 《Java从入门到失业》第一章:计算机基础知识(一):二进制和十六进制

    0 前言 最近7年来的高强度工作和不规律的饮食作息,压得我有些喘不过气,身体也陆续报警.2018年下半年的一场病,让我意识到了这个问题的严重性,于是开始强制自己有规律饮食和作息,并辅以健身锻炼,不到2 ...

  3. 《Java从入门到失业》第二章:Java环境(一):Java SE安装

    从这一章开始,终于我们可以开始正式进入Java世界了.前面我们提到过,Java分三个版本,我们这里只讨论Java SE. 2.1Java SE安装 所谓工欲善其事,必先利其器.第一步,我们当然是要下载 ...

  4. 《Java从入门到失业》第一章:计算机基础知识(三):程序语言简介

    1.3程序语言简介 我们经常会听到一些名词:低级语言.高级语言.编译型.解释型.面向过程.面向对象等.这些到底是啥意思呢?在正式进入Java世界前,笔者也尝试简单的聊一聊这块东西. 1.3.1低级语言 ...

  5. 《Java从入门到失业》第二章:Java环境(三):Java命令行工具

    2.3Java命令行工具 2.3.1编译运行 到了这里,是不是开始膨胀了,想写一段代码来秀一下?好吧,满足你!国际惯例,我们写一段HelloWorld.我们在某个目录下记事本,编写一段代码如下: 保存 ...

  6. 《Java从入门到失业》第二章:Java环境(二):JDK、JRE、JVM

    2.2JDK.JRE.JVM 在JDK的安装目录中,我们发现有一个目录jre(其实如果是下一步下一步安装的,在和JDK安装目录同级目录下,还会有一个jre目录).初学Java的同学,有时候搞不清楚这3 ...

  7. 《Java从入门到失业》第一章:计算机基础知识(二):计算机组成及基本原理

    1.2计算机组成及基本原理 1.2.1硬件组成 这里说的计算机主要指微型计算机,俗称电脑.一般我们见到的有台式机.笔记本等,另外智能手机.平板也算.有了一台计算机,我们就能做很多事情了,比如我在写这篇 ...

  8. 《Java从入门到失业》第四章:类和对象(4.5):包

    4.5包 前面我们已经听过包(package)这个概念了,比如String类在java.lang包下,Arrays类在java.util包下.那么为什么要引入包的概念呢?我们思考一个问题:java类库 ...

  9. #Python编程从入门到实践#第四章笔记

    #Python编程从入门到实践#第四章笔记   操作列表 ​​​1.遍历列表 使用for循环,遍历values列表 for value in values: print(value) 2.数字列表 使 ...

  10. ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区

    原文:ArcGIS for Desktop入门教程_第四章_入门案例分析 - ArcGIS知乎-新一代ArcGIS问答社区 1 入门案例分析 在第一章里,我们已经对ArcGIS系列软件的体系结构有了一 ...

随机推荐

  1. 计算机网络-传输层(3)TCP协议与拥堵控制

    TCP是因特网传输层的面向连接的可靠的运输协议.   TCP被称为是面向连接的:通信双方在发送数据之前必须建立连接,连接状态只在连接的两端中维护,在沿途节点中并不维护状态. TCP连接包括:两台主机上 ...

  2. Vue企业级优雅实战-00-开篇

    从2018.1.开始参与了多个企业的中台建设,这些中台的技术选型几乎都是基于 Spring Cloud 微服务架构 + 基于 Vue 全家桶的前端.我前后端架构及开发我几乎各占一半的精力,在企业级前端 ...

  3. mybatis逆向工程介绍

    项目的model一旦多了起来,复杂了起来,我们很自然的想到使用mybatis的逆向工程来生成相应的pojo和mapper,能节省很多精力. MyBatis Generator(MBG)是 MyBati ...

  4. ES6常用总结(一)

    let,const let声明变量,const声明常量,两者均为块级作用域 let,const在块级作用域内不允许重复声明 const声明的基本数据类型不可以修改,引用数据类型可以修改.具体看我的另一 ...

  5. 数字电路基础(二)TTL与非门输入端悬空和接大电阻的问题

    引言 我们在做那些判断与非门输入输出的时候,常常把输入端悬空和接大电阻作为高电平输入处理,比如下边这一例题: 很显然,我们无法直接从与非门逻辑图中看出其内部工作原理,那我们该如何分析呢?那肯定是去分析 ...

  6. vue init深度定制团队自己的Vue template

    大家都知道,使用vue-cli可以快速的初始化一个基于Vue.js的项目,全局安装脚手架之后,你可以通过vue list命令看到官方提供的5个模板 vue list 当开发一个独立项目的时候,使用官方 ...

  7. 15_Python的模块module

    1.模块的概述 1.模块是Python程序架构的一个核心概念,每一个以.py结尾的Python源代码文件都是一个模块 2.模块名和标识符的命名规则一样,由数字字母下划线组成且不能以数字开头,也不要和系 ...

  8. tomcat7升级到tomcat8注意事项

    第一点:context.xml配置jndi的参数修改   maxActive 替换为 :maxTotal maxWait 替换为 :maxWaitMillis factory="org.ap ...

  9. String字符串的最大长度是多少?

    在学习和开发过程中,我们经常会讨论 short ,int 和 long 这些基本数据类型的取值范围,但是对于 String 类型我们好像很少注意它的"取值范围".那么对于 Stri ...

  10. SpringBoot—整合log4j2入门和log4j2.xml配置详解

    关注微信公众号:CodingTechWork,一起学习进步. 引言   对于一个线上程序或者服务而言,重要的是要有日志输出,这样才能方便运维.而日志的输出需要有一定的规划,如日志命名.日志大小,日志分 ...