zoukankan      html  css  js  c++  java
  • 《Java从入门到失业》第四章:类和对象(4.6):类路径

    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大失叔workspaceBaseJavain

    C:Program FilesJavajre1.8.0_261lib

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

    D:Java大失叔workspaceBaseJavaincomjavadssjavasech04PackageTest.class

    C:Program FilesJavajre1.8.0_261libjavalangSystem.class

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

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

    D:Java大失叔workspaceBaseJavain; “C:Program FilesJavajre1.8.0_261lib”;

    在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大失叔workspaceBaseJavain D:Java大失叔workspaceBaseJavasrccomjavadssjavasech04aaaA.java

    javac -d D:Java大失叔workspaceBaseJavain D:Java大失叔workspaceBaseJavasrccomjavadssjavasech04bbB.java

    javac -d D:Java大失叔workspaceBaseJavain D:Java大失叔workspaceBaseJavasrccomjavadssjavasech04cccC.java

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

     

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

    javac -cp D:Java大失叔workspaceBaseJavain -d D:Java大失叔workspaceBaseJavain D:Java大失叔workspaceBaseJavasrccomjavadssjavasech04cccC.java

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

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

    D:Java大失叔workspaceBaseJavain;.;“C:Program FilesJavajre1.8.0_261lib”;

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

    set classpath=类路径集合

    例如:

    set classpath= D:Java大失叔workspaceBaseJavain; “C:Program FilesJavajre1.8.0_261lib”;

    我们在命令行窗口中执行上述命令后,在窗口关闭之前,所有的编译命令都不需要用-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大失叔workspaceBaseJavain com.javadss.javase.ch04.ccc.C

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

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

    我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2ayar2hbe7i8s

  • 相关阅读:
    Android实战开发租赁管理软件(适配UI,数据的存储,多线程下载)课程分享
    随 机 数 算 法
    java 状态模式 解说演示样例代码
    数据挖掘 决策树算法 ID3 通俗演绎
    经常使用表单数据的验证方法
    编程基本功训练:流程图画法及练�
    log4net使用具体解释
    妄想性仮想人格障害 新手教程 +改动器
    使用VS插件在VS2012/2013上编辑和调试Quick-Cocos2d-x的Lua代码
    经典回忆Effective C++ 1
  • 原文地址:https://www.cnblogs.com/javadss/p/13729331.html
Copyright © 2011-2022 走看看