跳至主要內容

Java

LincZero大约 11 分钟

Java

目录

模块系统

简概

在线API文档

String类包含许多方法。而且,在标准库中有几千个类,方法数量更加惊人。

要想记住所有的类和方法是一件不太不可能的事情。因此,学会使用在线API文档十分重要,从中可以查阅到标准类库中的所有类和方法。

API文档是JDK的一部分,它是HTML格式的。让浏览器指向安装JDK的docs/api/index.html子目录

  • Oracle_Java_官网API文档open in new window
    • 使用方法:API文档的三个窗格
    • 左上方显示了可使用的所有包,选择后对左下方的类进行一个筛选
    • 左下方显示了所有类,选择后右侧的文档进行该类的文档显示
    • 右侧显示选择类的文档,再点击里面的方法可以看到更详细的信息

包系统

与Python的包系统非常像,而并不像C++的include体系

  • 简概
    • Java允许使用包(package)将类组织起来。借助于包可以方便地组织自己的代码,并将自己的代码与别人提供的代码库分开管理
    • 标准的Java类库分布在多个包中,包括java.lang、java.util和java.net等
  • 作用
    • 使用包的主要原因是确保类名的唯一性。假如两个程序员不约而同地建立了Employee类。只要将这些类放置在不同的包中,就不会产生冲突。
  • 嵌套性
    • 标准的Java包具有一个层次结构,如同硬盘的目录嵌套一样,也可以使用嵌套层次组织包
    • 所有标准的Java包都处于java和javax(还有org?)包层次中
  • 其他补充:唯一性
    • 事实上,为了保证包名的绝对唯一性,Sun公司建议将公司的因特网域名以逆序的形式作为包名,并且对于不同的项目使用不同的子包
    • 例如,horstmann.com的逆序形式为com.horstmann。这个包还可以被进一步地划分成子包,如com.horstmann.corejava。
    • Android的软件包倒是使用了该方案

使用包(import)

三段式命名式命名

  • import xx.xx.xx 格式命名
  • 第一部分:java/javax/org
  • 第二部分:包名,小写开头
  • 第三部分:类名,大写开头,大驼峰命名
  • 第四部分:类下方法,可以为*表示导入所有方法

类的导入

第一种方式是在每个类名之前添加完整的包名。很繁琐

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

第二种方式是使用import语句

import java.util.*;					// import语句应该位于源文件的顶部(但位于package语句的后面)
LocalDate today = LocalDate.now();	// 在使用类时,就不必写出包的全名了

补充

只能使用星号(*)导入一个包,而不能使用import java.*import java.*.*导入以java为前缀的所有包

与C/C++不同

  • Java:包机制
  • C++:命名空间(namespace)
  • Java:import语句
  • C++:C++中的namespace和using指令

静态导入

(吐槽:傻逼翻译,静态方法和静态域什么鬼)

在源文件的顶部,添加一条静态导入的指令,就是导入类下的全部方法,使用时便不必加类名前缀

导入静态方法和静态域

import static java.lang.Syste.*;
// ...
out.println("Goodbye, World!");	// System.out
exit(0);						// System.exit

导入特定的方法和域

 import static java.lang.System.out;

将类放入包中

Employee.java

package com.horstmann.corejava;	// 将类放入该包中

public class Employee
{
    //...
}
  • 默认包
    • 如果没有在源文件中放置package语句,这个源文件中的类就被放置在一个默认包(defaulf package)中。默认包是一个没有名字的包。这里定义的所有类都在默认包中。
  • 路径
    • 将包中的文件放到与完整的包名匹配的子目录中。 例如,com.horstmann.corejava包中的所有源文件应该被放置在子目录com/horstmann/corejava(Windows中com\horstmann\corejava)中。 编译器将类文件也放在相同的目录结构中

使用默认包

  • 目录结构

    • 基目录

      ​ PackageTest.java # 在默认包中

      ​ PackageTest.class # 在默认包中

      ​ com/

      ​ horstmann/

      ​ corejava/

      ​ Employee.java

      ​ Employee.class

  • 编译

    • 要想编译这个程序,只需改变基目录,并运行命令

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

将类分别放在不同的包中

不使用默认包,而是将类分别放在不同的包中(com.horstmann.corejava和com.mycompany)

  • 目录结构

    • 基目录

      ​ com/

      ​ horstmann/

      ​ corejava/

      ​ Employee.java

      ​ Employee.class

      ​ mycompany/

      ​ PayrollApp.java

      ​ PayrollApp.class

  • 编译

    • 在这种情况下,仍然要从基目录编译和运行类,即包含com目录

    •  javac com/mycompany/PayrollApp.java
      java com.mycompany.PayrollApp
      

其他补充

从下一章开始,我们将对源代码使用包。这样一来,就可以为各章建立一个IDE工程,而不是各小节分别建立工程

包作用域

举例

public class Winodw extend Container
{
    String warningString;	// 该变量不是private,包中的所有方法都可以访问或设置该变量。不妥
    // ...
}

类路径(JAR,Java归档)[此略] 详见书

JAR文件

使用

  • 类文件也可以存储在JAR(Java归档)文件中。在一个JAR文件中,可以包含多个压缩形式的类文件和子目录,这样既可以节省又可以改善性能。
  • 在程序中用到第三方(third-party)的库文件时,通常会给出一个或多个需要包含的JAR文件。JDK也提供了许多的JAR文件,例如,在jre/lib/rt.jar中包含数千个类库文件。
  • JAR文件使用ZIP格式组织文件和子目录。可以使用所有ZIP实用程序查看内部的rt.jar以及其他的JAR文件

生成

为了使类能够被多个程序共享,需要做到下面几点

  • 把类放到一个目录中,例如/home/user/classdir。需要注意,这个目录是包树状结构的基目录。 如果希望将com.horstmann.corejava.Employee类添加到其中,这个Employee.class类文件就必须位于子录/home/user/classdir/com/horstmann/corejava中

  • 将JAR文件放在一个目录中,例如:/home/user/archives。

  • 设置类路径(class path)。类路径是所有包含类文件的路径的集合。

在UNIX环境中,类路径中的不同项目之间采用冒号(:)分隔

/home/user/classdir:.:/home/user/archives/archive.jar

在Windows环境中,则以分号(;)分隔

c:\classdir;.;c:\archives\archive.jar

设置类路径

最好采用-classpath(或-cp)选项指定类路径:

java -classpath /home/user/classdir:.:/home/user/archives/archive.jar MyProg

或者

java -classpath c:\classdir;.;c:\archives\archive.jar MyProg

文档注释 [此略] 详见书

概述:JDK包含一个很有用的工具,叫做javadoc,它可以由源文件生成一个HTML文档

优点:这种方式可以将代码与注释保存在一个地方。如果将文档存入一个独立的文件中,就有可能会随着时间的推移,出现代码和注释不一致的问题。然而,由于文档注释与源代码在同一个文件中,在修改源代码的同时,重新运行javadoc就可以轻而易举地保持两者的一致性。

注释的插入

基本使用

  • /**...*/文档注释在标记之后紧跟着自由格式文本(free-form text)

标记

  • 标记由@开始,如@author@param

自由格式文本

  • 第一句应该是一个概要性的句子。javadoc实用程序自动地将这些句子抽取出来形成概要页
  • 在自由格式文本中,可以使用HTML修饰符,例如:
    • 用于强调的<em>...</em>
    • 用于着重强调的<strong>...</strong>
    • 包含图像的<img...>等。
    • 注意:一定不要使用<h1><hr>,因为会与文档的格式产生冲突
  • 若要键入等宽代码,需使用{@code...}而不是<code>...</code>——这样一来,就不用操心对代码中的<字符转义了
  • 文件链接的处理:如果文档中有到其他文件的链接,例如,图像文件,就应该将这些文件放到子目录doc-files中 例如:<img src=“doc-files/uml.png”alt=“UML diagram”>

实战

类注释

类注释必须放在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
{
    ...
}

注意:没有必要在每一行的开始用星号*。然而,大部分IDE提供了自动添加星号*,并且当注释行改变时,自动重新排列这些星号的功能。

方法注释

常用标记

标记描述
@param 变量描述一个方法的所有@param标记必须放在一起。
这个描述可以占据多行,可以使用HTML标记
@return 描述
这个描述可以跨越多行,可以使用HTML标记
@throws 类描述用于表示这个方法有可能抛出异常
  • @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;
}

域注释

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

例如

/**
 * The "Hearts" card suit
 */
public static final int HEARTS = 1;

通用注释

常用标记

标记描述
@author 姓名可以使用多个@author标记,每个@author标记对应一个作者
@version 文本这里的文本可以是对当前版本的任何描述
@since 文本这里的text可以是对引入特性的版本描述。例如,@since version 1.7.1
@deprecated 文本这个标记将对类、方法或变量添加一个不再使用的注释
例如:@deprecated Use<code>setVisible (true) </code> instead
@see 引用通过@see和@link标记,可以使用超级链接,链接到javadoc文档的相关部分或外部文档。
  • @author 姓名,这个标记将产生一个“author”(作者)条目。可以使用多个@author标记,每个@author标记对应一个作者
  • @version 文本,将产生一个“version”(版本)条目。这里的文本可以是对当前版本的任何描述
  • 下面的标记可以用于所有的文档注释中
  • @since 文本,产生一个“since”(始于)条目。这里的text可以是对引入特性的版本描述。例如,@since version 1.7.1
  • @deprecated 文本,这个标记将对类、方法或变量添加一个不再使用的注释。文本中给出了取代的建议。
    • 例如:@deprecated Use<code>setVisible (true) </code> instead
  • @see 引用,通过@see和@link标记,可以使用超级链接,链接到javadoc文档的相关部分或外部文档
    • 例如:@see com.horstmann.corejava.Employee#raiseSalary(double)
    • 例如:@see <a href="www.horstmann.com/corejava.html">The Core Java home page</a>
    • 例如:@see "Core Java 2 volume 2"
    • 例如:{@link package.class#feature label}

包与概述注释

可以直接将类、方法和变量的注释放置在Java源文件中,只要用/**...*/文档注释界定就可以了。 但是,要想产生包注释,就需要在每一个包目录中添加一个单独的文件

有如下两个选择

  • (1) 提供一个以package.html命名的HTML文件。在标记<body>...</body>之间的所有文本都会被抽取出来。
  • (2) 提供一个以package-info.java命名的Java文件。这个文件必须包含一个初始的以/**和*/界定的Javadoc注释,跟随在一个包语句之后。它不应该包含更多的代码或注释。

注释的抽取

相关文档

  • 有关其他的选项,请查阅javadoc实用程序的联机文档,http://docs.oracle.com/javase/8/docs/guides/javadoc
  • 如果需要进一步的定制,例如,生成非HTML格式的文档,可以提供自定义的doclet,以便生成想要的任何输出形式。显然,这是一种特殊的需求,有关细节内容请查阅http://docs.oracle.com/javase/8/docs/guides/javadoc/doclet/overview.html的联机文档

假设HTML文件将被存放在目录docDirectory下。执行以下步骤:

1)切换到包含想要生成文档的源文件目录。如果有嵌套的包要生成文档,例如com.horstmann.corejava,就必须切换到包含子目录com的目录(如果存在overview.html文件的话,这也是它的所在目录)。

2)如果是一个包,应该运行命令:

javadoc -d docDirectory nameOfPackage

或对于多个包生成文档,运行:

javadoc -d docDirectory nameOfPackage1 nameOfPackage2 ...

如果文件在默认包中,就应该运行:

javadoc -d docDirectory *.java

如果省略了-d docDirectory选项,那HTML文件就会被提取到当前目录下。这样有可能会带来混乱,因此不提倡这种做法。