写点什么

Java 代码的组织机制

用户头像
michaelliu
关注
发布于: 2020 年 04 月 29 日
Java 代码的组织机制



在我们进行编程的时候会经常遇到一个相同的问题,就是命名冲突。不同的人可能会定义同样的类和接口名,Java 中解决这个问题的主要方法就是「包」



「包」类似计算机中的文件夹,正如我们在计算机管理文件,文件放在文件夹中一样,类和接口放在包中,文件夹一般是目录层次解决,Java 包也类似。



「包」有包名,这个名称以点号 . 分隔表示层次结构。比如,我们之前常用的 String 类就位于包 java.lang 下,其中 java 是上层包名,lang 是下层包名。带完整包名的类名称为其「完全限定名」,比如 String 类的完全限定名为 java.lang.String。Java API 中所有的类和接口都位于包 java 或 javax 下,java 是标准包,javax 是扩展包。

声明类所在的包



定义类的时候,应该先使用关键字 package 声明其包名



package com.lgq.study.bean;
public class User {
}

以上声明类 User 的包名为 com.lgq.study.bean 包声明语句应该位于源代码的最前面,前面不能有注释外的其他语句。



包名和目录结构必须匹配,如果源文件的根目录为 D:\src\,则上面的 User 类对应的文件 User.java,其全路径就应该是 D:\src\com\lgq\study\bean\User.java。如果不匹配, Java 会提示编译错误。



Java 中命名包名的一个惯例是使用域名作为前缀,因为域名是唯一的,一般按照域名的反序来定义包名,比如,域名是 apache.org,包名就以 org.apache 开头。



类的导入



同一个包下的类之间互相引用是不需要包名的,可以直接使用。但如果类不在同一个包内,则必须要知道其所在的包。只有一个例外,java.lang 包下的类可以直接使用,不需要引入,也不需要使用完全限定名,比如 String 类、System 类,其他包的类则不行。a



类的完全限定名导入类



public class Test {
public static void main(String[] args) {
int[] arr = new int[]{1, 4, 2, 3};
java.util.Arrays.sort(arr);
System.out.println(java.util.Arrays.toString(arr));
}
}

上面使用 Arrays 类中的 sort 方法,通过完全限定名可以这样使用。



将用到的类引入当前类



引入的关键字是 importimport 需要放在 package 定义之后,类定义之前:



package com.lgq.study;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
int[] arr = new int[]{1, 4, 2, 3};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
}



import 操作还有如下写法:



  • import java.util.* 引入 java.util 包下所有的直接类,而不会引入 java.util 下嵌套包内的类。



静态导入



静态导入有一个 static 关键字,可以直接导入类的公开静态方法和成员。



package com.lgq.study;
import java.util.Arrays;
import static java.lang.System.out; //导入静态变量 out
public class Test {
public static void main(String[] args) {
int[] arr = new int[]{1, 4, 2, 3};
Arrays.sort(arr);
out.println(Arrays.toString(arr)); //直接使用 out 变量
}
}



包的作用域



  • public:标记为 public 的部分可以被任意的类使用;

  • private:标记为 private 的部分只能被定义它们的类使用;

  • 如果没有指定 publicprivate,这个部分(类、方法或变量)可以被同一个包中的所有类访问,而其他包内的类则不可以访问。

  • protected:标记为 protected 的部分不仅表明子类可以访问,还表明同一个包内的其他类可以访问,即使这些类不是子类也可以。



protecteddefault 的区别就在于子类是否和父类在同级包中,protected 修饰的变量子类在其他包中也可以访问,但是 default 情况下的变量子类只能在同级包中才可以访问。



可见性范围从小到大是:private < 默认(包)< protected < public



JAR 文件



在 Java 中,编译后的一个或多个包的 Java class 文件可以打包为一个文件,Java 中打包命令为 jar,打包后的文件扩展名为 .jar,一般称之为 jar 包,JAR 文件是压缩的,它使用了大家熟悉的 ZIP 压缩格式。



打包方式如下,首先到编译后的 java class 文件根目录,然后运行如下命令:



jar -cvf hello.jar com

com 是最上层包名



程序的编译与链接



「编译」是将源代码文件变成扩展名是 .class 的一种字节码,这个工作一般是由 javac 命令完成的。



「链接」是在运行时动态执行的,.class 文件不能直接运行,运行的是 Java 虚拟机,执行的就是 java 命令,这个命令解析 .class 文件,转换为机器能识别的二进制代码,然后运行。所谓「链接」就是根据引用到的类加载相应的字节码并执行。



Java 编译和运行时,都需要以参数指定一个 classpath,即类路径。类路径可以有多个,对于直接的 class 文件,路径是 class 文件的根目录;对于 jar 包,路径是 jar 包的完整名称(包括路径和 jar 包名)。



在 Java 源代码编译时, Java 编译器会确定引用的每个类的完全限定名,确定的方式是根据 import 语句和 classpath。如果导入的是完全限定名,则可以直接比较并确定。如果是模糊导入(import 带 .*),则根据 classpath 找对应父包,再在父包下寻找是否有对应的类。如果多个模糊导入的包下都有同样的类名,则 Java 会提示编译错误,此时应该明确指定导入哪个类。



Java 运行时,会根据类的完全限定名寻找并加载类,寻找的方式就是在类路径中寻找,如果是 class 文件的根目录,则直接查看是否有对应的子目录及文件,如果是 jar 文件,则首先在内存中解压文件,然后再查看是否有对应的类。

参考资料



  • Java 编程的逻辑

  • Java编程思想

  • Java 核心技术 卷 1

用户头像

michaelliu

关注

Stay hungry, stay foolish. 2017.10.24 加入

120 %

评论

发布
暂无评论
Java 代码的组织机制