• 《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

  • 相关阅读:
    什么是webview
    juqery.fn.extend和jquery.extend
    LeetCode
    5. Longest Palindromic Substring
    42. Trapping Rain Water
    11. Container With Most Water
    621. Task Scheduler
    49. Group Anagrams
    739. Daily Temperatures
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/javadss/p/13729331.html
Copyright © 2020-2023  润新知