Java 包(学习 Java 编程语言 )

想你就写信 2021-01-21 23:21:01
java 编程 学习 语言


Java 允许使用包(package)将类组织在一个集合中。借助包可以方便地组织自己的代码,并将自己的代码与别人提供的代码库分开管理。

标准的 Java 类库分布在多个包中,包括 java.long、java.util 和 java.net 等。标准的 Java 包具有一个层次结构。所有标准的 Java 包都处于 java 和 javax 包层次中。

1. 包名

使用包的主要原因是确保类名的唯一性。事实上,为了确保包名的绝对唯一性,要用一个因特网域名(这显然是唯一的)以逆序的形式作为包名,然后对于不同的工程使用不同的子包。例如,域名 xiang117.com,逆序来写,得到包名 com.xiang117。然后可以追加一个工程名,如 com.xiang117.corejava。如果在把 Employee 类放在这个包里,那么这个类的 “完全限定” 名就是 com.xiang117.corejava.Employee。

从编译器的角度看来,嵌套的包之间没有任何关系。例如,java.util 包与 java.util.jar 包毫无关系。每一个包都是独立的类集合。

2. 类的导入

一个类可以使用所属包中的所有类,以及其他包中的公共类(public class)。
可以采用两种方式访问另一个包中的公有类:

  1. 使用完全限定名(fully qualified name),即包名后跟着类名。
    java.time.LocalData today = java.time.LocalDate.now();
  2. 使用 import 语句。

可以使用 import 语句导入一个特定的类或者整个包。import 语句应该位于资源文件的顶部(但位于 package 语句的后面)。

import 语句是一种引用包中各个类的简捷方式。一旦使用了 import 语句,在使用类时,就不必写出类的全名了。

import 语句的唯一好处是简捷。可以使用简短的名字而不是完整的包名来引用一个类。

可以使用下面语句导入 java.time 包中的所有类。 import java.time.*;
就可以使用 LocalDate today = localDate.now();
无需在前面加上包的前缀。

java.time.* 的语法比较简单,对代码的规模也没有任何负面影响。当然,如果能够明确地指出所导入的类,将会使代码的读者更加准确地知道你使用了哪些类。

需要注意的是,只能使用星号(_)导入一个包,而不能使用 import java._或import java._._ 导入以 java 为前缀的所有包。

可以导入一个包中的特定类: import java.time.LocalDate;

在大多数情况下,可以只导入所需要的包,并不必过多地考虑它们。但在发生命名冲突的时候,就要注意包了。例如,java.util 和 java.sql 包都有 Date 类。如果在程序中导入了这两个包: import java.util.; import java.sql.;
在程序使用 Date 类的时候,就会出现一个编译错误: Date today; // Error--java.util.Date or java.sal.Date?
此时编译器无法确定程序使用的是哪一个 Date 类。可以采用增加一个特定的 import 语句来解决这个问题: import java.util.; import java.sql.; import iava.util.Date;
如果这两个 Date 类都需要使用,需要在每个类名的前面加上完整的包名。 java.util.Date deadline = new java.util.Date(); java.sql.Date today = new java.sql.Date();

在包中定位类是编译器(compiler)的工作。类文件中的字节码总是使用完整的包名引用其他类。

3. 静态导入

有一种 import 语句允许导入静态方法和静态字段,而不只是类。

如果在源文件顶部,添加一条指令: import static java.lang.System.*;
就可以使用 System 类的静态方法和静态字段。而不必加类名前缀: out.println("Goodbye, World!"); // i.e., System.out exit(0); // i.e., System.exit

可以导入特定的方法或字段: import static java.lang.System.out;

实际上,是否有很多网站监控程序员想要用简写 System.out 或 System.exit,这一点让人怀疑。这样写出的代码看起来不太清晰。不过, sqrt(pow(x, 2) + pow(y, 2))
看起来比 Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2))
清晰得多。

4. 在包中增加类

要想将类放入包中,就必须将包的名字放在源文件的开头,即放在定义这个包中各个类的代码之前。例如在 com.xiang017.corejava 包中增加 Employee 类:

Employee.java

package com.xiang017.corejava;

public class Employee

{

...

}

如果没有在源文件中放置 package 语句,这个源文件中的类就属于_无名包(unnamed package)_。无名包没包名。

PackageTest.java

import com.xiang017.javacore.*;

public class PackageTest {

public static void main(String[] args) {

Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1);

}

}

将源文件放到与完整包名匹配的子目录中。例如,com.xiang017.corejava 包中的所有源文件应该放置在子目录 com/xiang017/corejava 中。编译器将类文件也放在相同的目录结构中。例如:

. (基目录)

PackageTest.java

└─com

└─xiang017

└─javacore

Employee.java

要想编译这个程序,只需切换到基目录,并运行命令: javac PackageTest.java
编译器就会自动地查找文件 com/xiang017/corejava/Employee.java 并进行编译。编译后的结果如下:

. (基目录)

PackageTest.class

PackageTest.java

└─com

└─xiang017

└─javacore

Employee.class

Employee.java

要运行这个程序,需要在基目录下执行命令: java PackageTest

假如 PackageTest.java 源文件没有在基目录下,在 mycompany 包下,如:

.(基目录)

|-- com/

|-- corejava/

| |-- Employe.java

| |-- Employe.class

|

|-- mycompany/

|-- PackageTest.java

|-- PackageTest.class

仍然要从基目录编译和运行类,即包含 com 目录的目录: javac com/mycompany/PackageTest.java java com.mycompany.PackageTest

需要注意,编译器对文件(带有文件分隔符的扩展名 .java 的文件)进行操作。而 Java 解释器加载类(带有 . 的分隔符)。

警告: 编译器在编译源文件的时候不检查目录结构。例如,假定有一个源文件开头有以下指令: package com.mycompany;
即使这个源文件不在子目录 com/mycompany 下,也可以进行编译。如果它不依赖于其他包,就可以通过编译而不会出现编译错误。但是,最终的程序将无法运行,除非先将所有的类文件移到正确的位置上。如果包与目录不匹配,虚拟机就找不到类。

PackageTest.java

import com.xiang017.javacore.*;

public class PackageTest {

public static void main(String[] args) {

Employee harry = new Employee("Harry Hacker", 50000, 1989, 10, 1);

System.out.println("name=" + harry.getName() +

",salary=" + harry.getSalary() +

",hireDay=" + harry.getHireDay());

}

}

com/mycompany/Employee.java

package com.xiang017.javacore;

import java.time.LocalDate;

import java.util.Objects;

public class Employee {

private String name;

private double salary;

private LocalDate hireDay;

public Employee(String name, double salary, int year, int month, int day) {

this.name = name;

this.salary = salary;

hireDay = LocalDate.of(year, month, day);

}

public String getName() {

return name;

}

public double getSalary() {

return salary;

}

public LocalDate getHireDay() {

return hireDay;

}

public void raiseSalary(double byPercent) {

double raise = salary * byPercent / 100;

salary += raise;

}

}

5. 包访问

标记为 public 的部分可以由任意类使用;标记为 private 的部分只能由定义它们的类使用。如果没有指定 public 或 private,这个部分(类、方法或变量)可以被同一个包中的所有方法访问。

没有标记修饰符的类只有在同一个包中其他类可以访问。对于类来说,这种默认方式是合乎情理的。但是,对于变量来说就有些不适宜了,变量必须显式地标记为 private,不然的话将默认为包可见。这样会破坏封装性。

在默认情况下,包不是一个封闭的实体。也就是说,任何人都可以向包中添加更多的类。

从 1.2 版开始,JDK 的实现者修改了类加载器,明确禁止加载包名以 “java.” 开头的用户自定义类!当然,用户自定义的类无法从这种保护中受益。另一种机制让 JAR 文件声明包为密封的(sealed),以防止第三方修改,但这种机制已经过时。现在应当使用模块封装包。

版权声明
本文为[想你就写信]所创,转载请带上原文链接,感谢
https://segmentfault.com/a/1190000039054772

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云