Java核心卷1知识点整理——第四章 对象与类(4.7-4.10)

4 篇文章 0 订阅
3 篇文章 0 订阅
4.7 包

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

标准的 Java 类库分布在多个包中,包括 java.lang、java.util 和java.net等。标准的 Java包具有一个层次结构。如同硬盘的目录嵌套一样,也可以使用嵌套层次组织包。所有标准的Java 包都处于java 和 javax 包层次中。

使用包的主要原因是确保类名的唯一性。假如两个程序员不约而同地建立了Employee类。只要将这些类放置在不同的包中, 就不会产生冲突。事实上,为了保证包名的绝对唯一性, Sun 公司建议将公司的因特网域名(这显然是独一无二的) 以逆序的形式作为包名,并且对于不同的项目使用不同的子包。例如,horstmann.com 是本书作者之一注册的域名。逆序形式为com.horstmann。这个包还可以被进一步地划分成子包,如 com.horstmann.corejava。

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

4.7.1 类的导入

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

第一种方法是在每个类名之前添加完整的包名。例如:

java.time.LocalDate today = java.time.LocalDate.now();

这显然很繁琐。更简单且更常用的方式是使用 import 语句。import 语句是一种引用包含在包中的类的简明描述。一旦使用了 import 语句,在使用类时,就不必写出包的全名了。

可以使用 import 语句导入一个特定的类或者整个包。import 语句应该位于源文件的顶部(但位于 package 语句的后面)。例如, 可以使用下面这条语句导入 java.util 包中所有的类。

import java.util.*;

然后就可以使用:

LocalDate today = LocalDate.now();

而无须在前面加上包前缀。还可以导入一个包中的特定类:

import java.time.LocalDate;

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

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

在大多数情况下,只导入所需的包,并不必过多地理睬它们。但在发生命名冲突的时候,就不能不注意包的名字了。例如,java.utiljava.sql 包都有日期Date类。如果在程序中导入了这两个包:

import java.util.*;
import java.sql.*;

在程序使用Date类的时候,就会出现一个编译错误:

Date today; // Error--java.util.Date or java.sql.Date?

此时编译器无法确定程序使用的是哪一个 Date 类。可以采用增加一个特定的 import 语句来解决这个问题:

import java.util.*;
import java.sql.*;
import java.util.Date;

如果这两个 Date 类都需要使用,又该怎么办呢? 答案是,在每个类名的前面加上完整的包名。

java.util.Date deadline = new java.util.Date();
java.sql.Date today = new java.sql.Date(...);

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

4.7.2 静态导入

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;

但是有时候,这样的编写形式不利代码的清晰度。

4.7.3 将类放入包中

要想将一个类放人包中, 就必须将包的名字放在源文件的开头,包中定义类的代码之前。

package com.horstmann.corejava;

public class Employee {
  ...
}

如果没有在源文件中放置 package 语句, 这个源文件中的类就被放置在一个**默认包(defaulf package)**中。默认包是一个没有名字的包。在此之前,我们定义的所有类都在默认包中。

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

如果Employee类的开头是 package com/horstmann/corejava,那么Employee.java源文件必须放在子目录com/horstmann/corejava中。例如:
在这里插入图片描述
PackageTest 类放置在默认包中;Employee 类放置在 com.horstmann.corejava 包中。

要想编译这个程序,只需切换到基目录,并运行命令:

javac PackageTest.java

编译器就会自动地查找文件 com/horstmann/corejava/Employee.java 并进行编译。

下面看一个更实际的例子,在这里不适用默认包,而是将类分发在不同的包中(com.horstmann.corejavacom.mycompany)
在这里插入图片描述
在这种情况下,仍然要从基目录编译和运行类,即包含 com 目录:

javac com/mycompany/PayrollApp.java

java com.mycompany.PayrollApp

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

警告⚠️:编译器在编译源文件的时候不检查目录结构。例如,假定有一个源文件开头有下列语句:

package com.mycompany;

即使这个源文件没有在子目录 com/mycompany 下, 也可以进行编译。如果它不依赖于其他包, 就不会出现编译错误。但是, 最终的程序将无法运行, 除非先将所有类文件移到正确的位置上。 如果包与目录不匹配, 虚拟机就找不到类

4.7.4 包的作用域

前面已经接触过访问修饰符 publicprivate。标记为 public 的部分可以被任意的类使用;标记为 private 的部分只能被定义它们的类使用。如果没有指定 publicprivate , 这个部分(类、方法或变量)可以被同一个包中的所有方法访问

4.9 文档注释
4.9.2 类注释

类注释必须放在import语句之后,类定义之前

例如:

/**
 * A {©code Card} object represents a playing card, such
 * as "Queen of Hearts. A card has a suit (Diamond, Heart, 
 * Spade or Club) and a value (1 = Ace, 2 . . . 10, 11 = Jack, 
 * 12 = Queen, 13 = King) 
 */
public class Card {
  ...
}
4.9.3 方法注释

每一个方法注释必须放在所描述的方法之前。除了通用标记之外, 还可以使用下面的标记:

  • @param变量描述

    这个标记将对当前方法的param(参数)部分添加一个条目。这个描述可以占据多行, 并可以使用 HTML 标记。一个方法的所有 @param 标记必须放在一起。

  • @return描述

    这个标记将对当前方法添加return(返回)部分。这个描述可以跨越多行, 并可以使用 HTML 标记。

  • @throws类描述

    这个标记将添加一个注释,用于表示这个方法有可能抛出异常。

下面是一个方法注释的示例:

/**
 * Raises the salary of an employee. 
 * @param byPercent the percentage by which to raise the salary (e.g. 10 means 10%) 
 * ©return the amount of the raise
 */
public double raiseSalary(double byPercent) {
  double raise = salary * byPercent / 100;
  salary += raise;
  return raise;
}
4.9.4 域注释

只需要对公有域(通常指的是静态常量)建立文档。例如:

/**
 * The "Hearts" card suit
 */
public static final int HEARTS = 1;
4.9.5 通用注释

下面的标记可以用在类文档的注释中:

  • @author name

    这个标记将产生一个 author (作者)条目。可以使用多个 @author 标记,每个 @author 标记对应一个作者

  • @version text

    这个标记将产生一个version(版本)条目。这里的text可以是对当前版本的任何描述。

下面的标记可以用于所有的文档注释中:

  • @since text

    这个标记将产生一个since(始于)条目。这里的 text 可以是对引人特性的版本描述。例如, @since version 1.7.10

  • @deprecated text

    这个标记将对类、 方法或变量添加一个不再使用的注释。text中给出了取代的建议。

    例如:

    @deprecated Use <code> setVisible(true) </code> instead

通过@see@link标记,可以使用超级链接,链接到javadoc文档的相关部分或外部文档。

  • @see reference

    这个标记将在“ see also” 部分增加一个超级链接。它可以用于类中,也可以用于方

    法中。这里的reference可以选择下列情形之一:

    package.class#feature label

    <a href="...">label</a>

    "text"

第一种情况是最常见的。只要提供类、 方法或变量的名字,javadoc 就在文档中插入一个超链接。例如,

@see com.horstmann.corejava.Employee#raiseSalary(double)

建立一个链接到 com.horstmann.corejava.Employee 类的 raiseSalary(double) 方法的超链接。可以省略包名, 甚至把包名和类名都省去,此时,链接将定位于当前包或当前类

需要注意,一定要使用井号(#), 而不要使用句号(.)分隔类名与方法名,或类名与变量名。

第二种情况,如果@see后面跟着<字符,就需要指定一个超链接。可以链接到任何URL,例如:

@see <a href="www.horstmann.com/corejava.html">The Core Java home page</a>

在上述各种情况下, 都可以指定一个可选的label作为链接锚(link anchor) 如果省略了 label , 用户看到的锚的名称就是目标代码名或 URL。

第三种情况,如果@see后面跟着"双引号字符,text就会显示在 ”see also“部分。例如:

@see "Core Java 2 volume 2"

可以为一个特性添加多个 @see 标记,但必须将它们放在一起。

  • 可以在注释中的任何位置放置指向其他类或方法的超级链接, 以及插人一个专用的标记, 例如:

    {@link package.class#feature label}

    这里的特性描述规则与@see标记规则一样。

4.10 类设计技巧
  1. 一定要保证保证数据私有

  2. 一定要对数据初始化

  3. 不要在类中使用过多的基本类型

    就是说,用其他的类代替多个相关的基本类型的使用。这样会使类更加易于理解且易于修改。例如, 用一个称为 Address 的新的类替换一个 Customer 类中以下的实例域:

    private String street;
    private String city;
    private String state;
    private int zip;
    
  4. 不是所有的域都需要独立的域访问器和域更改器

    或许,需要获得或设置雇员的薪金。而一旦构造了雇员对象,就应该禁止更改雇用日期,并且在对象中,常常包含一些不希望别人获得或设置的实例域。例如,在 Address 类中,存放州缩写的数组。

  5. 将职责过多的类进行分解

  6. 类名和方法名要能够体现它们的职责

  7. 优先使用不可变类

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值