# Java 包

原文：http://zetcode.com/lang/java/packages/

在 Java 教程的这一部分中，我们将讨论 Java 包。

程序包是一组相关类型的组合，提供访问保护和名称空间管理。 Java 中的包与 C# 中的名称空间类似。

## 使用 Java 创建包

使用`package`关键字声明包。 该语句必须放在每个源文件的顶部。 每个源文件中只能有一个这样的语句。 Java 源文件必须放在与包名称匹配的目录中。

```java
package com.zetcode;

```

使用上述包的文件中定义的所有类型都是`com.zetcode`包的一部分。 类`Being`具有完全限定的名称`com.zetcode.Being`。 全球有数百万的 Java 程序员。 为避免潜在的名称冲突，Java 中有一个命名约定。 程序包名称使用反向互联网域名。 字母以小写字母书写。 只能有一个`zetcode.com`域名，因此对于包使用反向名称`com.zetcode`将使它们唯一。 带有`com.zetcode`包的 Java 源文件必须位于`com/zetcode`子目录中。 包名称以小写形式编写，以避免与类或接口的名称冲突。

`import`关键字在源文件的开头用于指定类型（类，接口，枚举或注解）或以后要引用的整个 Java 包，而不在引用中包含它们的包名称。 从 Java SE 5.0 开始，`import`语句可以导入类的静态成员（方法和变量）。

```java
import java.awt.*;

```

使用*通配符，我们可以一次导入整个包。 导入后，我们可以引用所有`java.awt`包类型，而无需使用其全限定名。

```java
import java.awt.event.*;

```

`java.awt.event`子包未随`java.awt.*`导入一起导入。 子包必须独立导入。

```java
import java.util.Random;

```

在这种情况下，仅导入`Random`类。 现在可以使用其简单的类名来引用`Random`类。

## Java8 中的核心包

以下是 Java8 中的核心包的列表：

*   `java.lang` — 基本语言功能和基本类型
*   `java.util` — 集合数据结构类
*   `java.io` - 用于文件操作的 Java API
*   `java.math` — 多精度算术
*   `java.nio` — Java 的非阻塞 I/O 框架
*   `java.net` — 网络操作，套接字，DNS 查找，...
*   `java.security` — 密钥生成，加密和解密
*   `java.sql` — 用于访问数据库的 Java 数据库连接（JDBC）
*   `java.awt` — 本机 GUI 组件的基本包层次结构
*   `javax.swing` — 与平台无关的丰富 GUI 组件的包层次结构
*   `java.applet` - 用于创建小程序的类
*   `java.beans` - 包含与开发 bean 有关的类-基于 JavaBean 体系结构的组件。
*   `java.text` — 提供用于以独立于自然语言的方式处理文本，日期，数字和消息的类和接口。
*   `java.rmi` — 用于远程方法调用的 Java API。
*   `java.time` — 日期，时间，瞬间和持续时间的主要 API。

`java.lang`程序包不使用导入语句即可使用。

## 实际例子

以下示例显示了如何创建包和导入类型。

`Packages.java`

```java
package com.zetcode;

import java.util.Random;

public class Packages {

    public static void main(String[] args) {

        Random r = new Random();

        int x = r.nextInt();
        System.out.println(x);

        java.util.Calendar c = java.util.Calendar.getInstance();
        System.out.println(c.getTime());    
    }
}

```

该示例使用两种类型：`Random`类和`Calendar`类。 第一类是导入的，第二类是由其完全限定的名称引用的。

```java
package com.zetcode;

```

我们用`package`关键字声明一个包。 `Packages.java`文件必须位于`com/zetcode`子目录中。

```java
import java.util.Random;

```

此代码行使我们可以使用不带包名称的`Random`类。

```java
Random r = new Random();

```

在这里，我们使用`Random`而不使用其全名。

```java
java.util.Calendar c = java.util.Calendar.getInstance();

```

如果我们没有在类型上使用`import`关键字，则在本例中只能使用其全名-`java.util.Calendar`来引用它。 `import`关键字可以节省很多打字时间。

```java
$ ls com/zetcode/
Packages.java

```

`Packages.java`源文件位于`com/zetcode`子目录中。 程序包名称必须反映目录结构。

```java
$ javac com/zetcode/Packages.java 

```

我们使用`javac`工具编译源文件。 该工具从`com/zetcode`目录的父目录中调用。

```java
$ java com.zetcode.Packages 
179489124
Thu Jan 19 20:53:08 CET 2017

```

这是`com.zetcode.Packages`程序的输出。

## Java 包级别可见性

如果我们未指定任何访问修饰符（例如`private`，`protected`或`public`），那么我们将获得包私有的可见性。 在这种情况下，变量和方法可在同一包中访问。 其他程序包中的类无法访问通过程序包私有访问声明的类和成员。

## Java 默认包

如果未声明任何包，则该文件中定义的所有类型都是默认未命名包的一部分。 建议始终将您的类型放在包装中。 即使是小型程序。

`DefaultPackage.java`

```java
public class DefaultPackage {

    public static void main(String[] args) {

        System.out.println("A class in a default package");   
    }    
}

```

`DefaultPackage`类是默认包的一部分。

```java
$ ls
DefaultPackage.java

```

如果未指定包，则不会将源文件放置在特定的子目录中。

```java
$ javac DefaultPackage.java 
$ java DefaultPackage 
A class in a default package

```

我们编译代码并运行应用。 源文件和字节码位于当前工作目录中。

## Java 自动导入

Java 编译器自动导入两个包：`java.lang`和当前包。

`Constants.java`

```java
package com.zetcode;

public class Constants {

    public static final String version = "1.0";
}

```

`Constants`类与引用其版本成员的`AutomaticImports`位于同一包中。

`AutomaticImports.java`

```java
package com.zetcode;

public class AutomaticImports {

    public static void main(String[] args) {

        String os = System.getProperty("os.name");

        System.out.println(os);
        System.out.println(Constants.version);    
    }
}

```

在此示例中，我们引用了 Java 编译器自动导入的一些类。

```java
String os = System.getProperty("os.name");

```

`String`和`System`类是`java.lang`程序包的一部分。

```java
System.out.println(Constants.version);    

```

`Constants`类与`AutomaticImports`类位于同一包中。 因此，我们可以访问类及其成员，而无需使用完全限定的名称或使用`import`关键字。

```java
$ ls com/zetcode/
AutomaticImports.java  Constants.java

```

`AutomaticImports.java`和`Constants.java`文件都位于同一子目录中。

```java
$ javac com/zetcode/AutomaticImports.java com/zetcode/Constants.java

```

这两个文件都被编译。

```java
$ java com.zetcode.AutomaticImports 
Linux
1.0

```

这是`com.zetcode.AutomaticImports`程序的示例输出。

## Java 静态导入

如果我们经常使用一些静态成员，则可以稍后使用`import static`语句来引用它们，而无需使用完整的类名。 静态导入应谨慎使用。

`StaticImport.java`

```java
package com.zetcode;

import static java.lang.Math.E;
import static java.lang.Math.PI;
import static java.lang.Math.abs;

public class StaticImport {

    public static void main(String[] args) {

        System.out.println(E);
        System.out.println(PI);

        System.out.println(abs(-5));    
    }
}

```

在此示例中，我们引用两个常量和一个静态方法。

```java
import static java.lang.Math.E;
import static java.lang.Math.PI;
import static java.lang.Math.abs;

```

我们使用`import static`语句启用不带全名的引用。

```java
System.out.println(E);
System.out.println(PI);

System.out.println(abs(-5));  

```

我们引用这三个成员时没有其类名。

```java
$ java com.zetcode.StaticImport 
2.718281828459045
3.141592653589793
5

```

这是`com.zetcode.StaticImport`程序的输出。

本章介绍了 Java 中的包。 我们已经展示了如何在包中组织代码。