内容


第 4 单元:Java 语言入门

了解 Java 对象如何构成

Comments

开始之前

本单元是 “Java 编程入门” 课程的一部分。尽管各单元中讨论的概念具有独立性,但实践组件是在您学习各单元的过程中逐步建立起来的,推荐您在继续学习之前复习 前提条件、设置和单元细节

单元目标

  • 认识 Java 语言中的保留字
  • 理解 Java 类与 Java 对象之间的关系。
  • 了解 Java 类中的每种结构的功能和语法

OOP 与对象密切相关。本单元介绍两个与 Java 语言如何处理对象紧密相关的主题:保留字和 Java 类的结构。

保留字

跟任何编程语言一样,Java 语言指定了一些编译器认为具有特殊含义的关键字。出于该原因,不允许您使用它们来命名您的 Java 结构。保留字(也称为关键字)非常少:

abstract
assert
boolean
break
byte
case
catch
char
class
const
continue
default
do
double
else
enum
extends
final
finally
float
for
goto
if
implements
import
instanceof
int
interface
long
native
new
package
private
protected
public
return
short
static
strictfp
super
switch
synchronized
this
throw
throws
transient
try
void
volatile
while

您也不可以使用 truefalsenull(技术上讲,它们是 字面常量 而不是关键字)来命名 Java 结构

稍后将会看到,使用 IDE 编程的一个优势是,它可以为保留字使用语法颜色。

Java 类的结构

类是一个包含属性和行为的离散实体(对象)的蓝图。类定义对象的基本结构,在运行时,您的应用程序会创建对象的实例。对象拥有明确定义的边界和状态,它可在被正确请求时执行操作。每种面向对象的语言都拥有有关如何定义类的规则。

在 Java 语言中,类的定义如清单 1 所示:

清单 1. 类定义
package packageName;
import ClassNameToImport; 
accessSpecifier class ClassName {
  accessSpecifier dataType variableName [= initialValue];
  accessSpecifier ClassName([argumentList]) {
    constructorStatement(s)
  }
  accessSpecifier returnType methodName ([argumentList]) {
    methodStatement(s)
  }
  // This is a comment
  /* This is a comment too */
  /* This is a
     multiline
     comment */
}

清单 1 包含各种不同的结构类型,第 1 行是 package,第 2 行是 import,第 3 行是 class。这 3 种结构都属于 保留字,所以它们必须保持清单 1 中的准确格式。我为清单 1 中的其他结构提供的名称描述了它们表达的概念。

可以注意到 清单 1 中的第 11 到 15 行是注释行。在大多数编程语言中,程序员都可添加注释来帮助描述代码。Java 语法允许单行和多行注释。

// This is a comment
/* This is a comment too */
/* This is a
multiline
comment */

单行注释必须包含在一行上,但您可使用邻近的单行注释来形成一个注释组。多行注释以 /* 开头,必须以 */ 终止,而且可以涵盖任意多行。

接下来,我将详细介绍 清单 1 中的结构,首先看看 package

打包类

在 Java 语言中,您可选择类的名称,比如 AccountPersonLizardMan。有时,您可能最终使用了同一个名称来表达两个稍微不同的概念。这种情形称为名称冲突,经常会发生。Java 语言使用 来解决这些冲突。

Java 包是一种提供命名空间 的机制— 名称在命名空间中是唯一的,但在其外部可能不是唯一的。要唯一地标识一个结构,您必须包含它的命名空间来完全限定它。

包也是利用多个离散功能单元来构造更复杂应用程序的不错方式。

要定义包,可使用 package 关键字,后跟一个合法的包名称,并以一个分号结尾。包名称常常遵循这种事实标准模式:

package  orgType.orgName.appName.compName;

这个包定义可分解为:

  • orgType 是组织类型,比如 comorgnet
  • orgName 是组织的域名称,比如 makotojavaoracleibm
  • appName 是缩写的应用程序名称。
  • compName 是组件的名称。

本课程将使用此约定,而且我推荐坚持使用它来定义包中的所有 Java 类。(Java 语言没有强制要求您遵循这种包约定。您完全不需要指定一个包,但在这种情况下,您的所有类必须具有唯一名称且将位于默认包中。)

导入语句

类定义中的下一部分(返回参考 清单 1)是导入语句。导入语句告诉 Java 编译器在何处查找您在代码中引用的类。任何非简单的类都会使用其他类来实现某种功能,导入语句是您向 Java 编译器告知这些类的方式。

导入语句通常类似于:

import ClassNameToImport;

您指定 import 关键字,后跟您想要导入的类,然后输入一个分号。类名应是完全限定的,意味着名称中应包含它的包。

要导入一个包中的所有类,您可将 .* 放在包名称后。例如,这条语句导入 com.makotojava 包中的每个类:

import com.makotojava.*;

但是,导入整个包会降低代码的可读性,所以我推荐使用完全限定名称来仅导入需要的类。

类声明

要在 Java 语言中定义一个对象,必须声明一个类。可将类视为对象的模板,就像饼干模具一样。

清单 1 包含以下类声明:

accessSpecifier class ClassName {
  accessSpecifier dataType variableName [= initialValue];
    accessSpecifier ClassName([argumentList]) {
    constructorStatement(s)
  }
  accessSpecifier returnType methodName([argumentList]) {
    methodStatement(s)
  }
}

类的 accessSpecifier 可拥有多个值,但该值通常为 public。您很快会看到 accessSpecifier 的其他值。

可以将类命名为您想要的任何名称,但约定是使用驼峰式大小写:以一个大写字母开头,但将串联的每个单词的第一个字母大写,将所有其他字母小写。类名应仅包含字母和数字。坚持这些准则,可确保代码更容易供其他遵循相同约定的人使用。

变量和方法

类可拥有两种类型的成员变量方法

变量

类的变量的值可以区分该类的每个实例并定义它的状态。这些值常常称为实例变量。一个变量有:

  • 一个 accessSpecifier
  • 一个 dataType
  • 一个 variableName
  • 一个可选的 initialValue

可能的 accessSpecifier 值包括:

  • public:任何包中的任何对象都能看到该变量。(不要使用此值;请参阅公共变量边栏。)
  • protected:在同一个包中或(在任何包中定义的)一个子类中定义的任何对象都能看到此变量。
  • 没有修饰符(也称为友好包私有 访问):仅在同一个包中定义的类的对象能够看到此变量。
  • private:只有包含该变量的类能够看到它。

变量的 dataType 取决于变量的类型— 它可能是一种原语类型或另一种类类型(稍后将更详细地介绍)。

variableName 由您自己决定,但根据约定,变量名使用驼峰式大小写约定,但它们以小写字母开头。(这种样式有时称为小驼峰式大小写。)

现在暂时不要关心 initialValue,只需知道可以在声明一个实例变量时初始化它。(否则,编译器会为您生成一个在实例化该类时设置的默认值。)

示例:Person 的类定义

这个示例总结了您目前所学的知识。清单 2 是 Person 的类定义。

清单 2. Person 的基类定义
package com.makotojava.intro;

public class Person {
   private String name;
   private int age;
   private int height;
   private int weight;
   private String eyeColor;
   private String gender;
}

Person 的这个基类定义目前不是很有用,因为它仅定义了 Person 的属性(而且是私有属性)。要更加完整,Person 类还需要行为 —也就是方法

方法

类的方法定义它的行为。

方法分为两个主要类别:构造方法;以及所有其他方法,这些方法具有许多类型。构造方法仅用于创建类的实例。其他类型的方法可用于几乎任何应用程序行为。

清单 1 中的类定义给出了定义方法的结构的方式,该结构包括的元素有:

  • accessSpecifier
  • returnType
  • methodName
  • argumentList

这些结构元素在方法定义中的组合称为方法的签名

现在仔细看看两种方法类别,首先看看构造方法。

构造方法

可使用构造方法指定如何实例化类。清单 1 以抽象形式给出了构造方法声明语法;这里再次给出了它:

accessSpecifier ClassName([argumentList]) {
  constructorStatement(s)
}

构造方法的 accessSpecifier 与变量的相同。构造方法的名称必须与类名匹配。所以如果您将类命名为 Person,构造方法的名称必须也是 Person

对于任何其他不是默认构造方法的构造方法(参见构造方法是可选的边栏),您需要传递一个 argumentList,其中包含一个或多个:

argumentType argumentName

argumentList 中的参数用逗号分隔,而且任何两个参数不能具有相同名称。argumentType 是一种原语类型或另一种类类型(与变量类型相同)。

包含构造方法的类定义

现在来看看在添加了通过两种方式创建 Person 对象的能力后会发生什么:通过使用 no-arg 构造方法和通过初始化一个部分属性列表。

清单 3 展示了如何创建构造方法,以及如何使用 argumentList

清单 3. 包含构造方法的 Person 类定义
package com.makotojava.intro;
public class Person {
  private String name;
  private int age;
  private int height;
  private int  weight;
  private String eyeColor;

  private String gender;
  public Person() {
    // Nothing to do...
  }

  public Person(String name, int age, int height, int weight String eyeColor, String gender) {
    this.name = name;
    this.age = age;
    this.height = height;
    this.weight = weight;
    this.eyeColor = eyeColor;
    this.gender = gender;
  }
}

可以注意到,清单 3 中使用了 this 关键字来执行参数赋值。this 关键字是 “this object” 的 Java 速记形式,在引用两个具有相同名称的变量时必须使用它。在本例中,age 既是一个构造方法参数,又是一个类变量,所以 this 关键字可帮助编译器消除引用的歧义。

Person 对象变得越来越有趣了,但它需要有更多行为。为此,您需要更多方法。

其他方法

构造方法是一种具有特定功能的特定方法类型。类似地,其他许多类型的方法执行 Java 程序中的特定功能。从本节到本课程结束,将探索其他方法类型。

返回到 清单 1 中,可以看到方法的声明方式:

accessSpecifier returnType methodName ([argumentList]) {
  methodStatement(s)
}

其他方法看起来非常像构造方法,但有两处例外。首先,您可为其他方法提供您喜欢的任何名称(但是,肯定要遵守某些规则)。我推荐以下约定:

  • 以小写字母开头。
  • 避免使用数字,除非确实有必要使用它们。
  • 仅使用字母字符。

第二,不同于构造方法,其他方法拥有一个可选的返回类型

Person 的其他方法

有了这些基本信息,您就可以在清单 4 中看到在向 Person 对象添加一些方法后发生的情况。(为简洁起见,我省略了构造方法。)

清单 4. 包含一些新方法的 Person
package com.makotojava.intro;

public class Person {
   private String name;
   private int age;
   private int height;
   private int  weight;
   private String eyeColor;
   private String gender;

   public String getName() { return name; }
   public void setName(String value) { name = value; }
   // Other getter/setter combinations...
}

请注意 清单 4 中有关 “getter/setter 组合” 的注释。稍后会更多地使用 getter 和 setter。就现在而言,您只需知道 getter 是一个检索属性值的方法,setter 是一个修改该值的方法。清单 4 仅给出了一种 getter/setter 组合(针对 Name 属性),但您可通过类似方式定义更多组合。

清单 4 中可以注意到,如果一个方法没有返回值,您必须在该方法的签名中指定 void 返回类型来告诉编译器。

静态和实例方法

通常会使用两种类型的(非构造)方法:实例方法静态方法。实例方法依赖于特定对象实例的状态来执行其行为。静态方法有时也称为类方法,因为它们的行为不依赖于任何一个对象的状态。静态方法的行为在类级别上发生。

静态方法主要用于实用程序;您可将它们视为全局方法(类似于 C 语言),但将该方法的代码与定义它的类放在一起。

例如,在后面各节中,将使用 JDK Logger 类向控制台输出信息。要创建一个 Logger 类实例,不需要实例化一个 Logger 类;而是调用一个名为 getLogger() 的静态方法。

在类上调用静态方法的语法不同于在对象上调用方法的语法。您还会使用包含该静态方法的类的名称,如这个调用中所示:

Logger l = Logger.getLogger("NewLogger");

在这个示例中,Logger 是类名,getLogger(...) 是方法名。所以要调用静态方法,您不需要对象实例,只需要类名。

测试您的理解情况

  1. 导入语句有何用途?
    1. 除了提醒程序员您的类依赖关系,它们没有任何实际用途。
    2. 它们供 Web 软件用于连接一些网站和下载相关代码。
    3. 它们用于告诉编译器您的类引用了哪些类。
    4. 上述选项都不是
  2. 如果您想要一个变量仅在定义它的类中可见,应为它提供哪个 accessSpecifier
    1. public
    2. private
    3. 不提供,因为这是编译器的默认 accessSpecifier
    4. protected
    5. 上述选项都不是
  3. Java 语言中的保留字是什么?
    1. 一些为 Java 运行时保留的文字或短语,以便编译器编译代码之前删除它们。
    2. 您不能用于命名结构,在 Java 语言中具有特殊含义的文字(也称为关键字)。
    3. Java 语言中没有所谓的 “保留字”。
    4. 一些被编译器忽略的文字,类似于注释。
    5. 上述选项都不是。
  4. 包用于创建一个区域(称为命名空间),名称在该区域中是唯一的,但在外部可能不是唯一的。
    1. 它依赖于编译器上下文。
    2. Java 语言中没有所谓的 “包”。
    3. 上述选项都不是
  5. 清单 4Person 类添加了多个属性。作为练习,编写 getter/setter 代码来访问/设置这些值。使用 getName()/setName() 方法作为示例。
  6. 清单 3 中,定义了一个替代性构造方法和 no-arg 构造方法,尽管 no-arg 方法不执行任何操作。为什么可以在此场景中声明 no-arg 构造方法?
    1. 如果不在每个类中定义 no-arg 构造方法,您将获得编译器错误。
    2. 通过提供 no-arg 构造方法,您可以创建一个空 Person 对象,将它的属性设置为默认值。
    3. 清单 3 中的代码是错误的。它不会编译,因为同一个类上不能有两个构造方法。
    4. 不存在所谓的 no-arg 构造方法。这是一个陷阱问题。
    5. 上述选项都不是
  7. 静态方法与实例方法有何区别?
    1. 两种方法之间几乎没有区别。
    2. 静态方法可从任何语言调用,而实例方法仅允许在一个对象中使用。
    3. 在对象上调用实例方法需要该对象的引用,而调用静态方法不需要。
    4. 静态方法 “绑定” 到定义它的对象,而实例方法可在对象之间流动。

核对您的答案

进一步探索

Java 语言规范

Java 语言基础

类和对象

Benjamin J. Evans 和 David Flanagan 编写的 Java 技术手册第 6 版

Kathy Sierra 和 Bert Bates 编写的 Head First Java 第 2 版

Herbert Schildt 编写的 Java:入门指南第 6 版

上一单元:面向对象的概念和原理下一单元:您的第一个 Java 类


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=1038293
ArticleTitle=第 4 单元:Java 语言入门
publish-date=10112016