在单个教程中介绍整个 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
您也不可以使用 true
、false
和 null
(技术上讲,它们是而不是关键字)来命名 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 和本节的其他一些代码示例中,方括号表示它们之中的结构不是必需的。方括号(不同于 {
和 }
)不是 Java 语法的一部分。
清单 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 语言中,您可选择类的名称,比如 Account
、Person
或 LizardMan
。有时,您可能最终使用了同一个名称来表达两个稍微不同的概念。这种情形称为 名称冲突 ,经常会发生。Java 语言使用 包 来解决这些冲突。
Java 包是一种提供 命名空间 的机制 — 名称在命名空间中是唯一的,但在其外部可能不是唯一的。要唯一地标识一个结构,您必须包含它的命名空间来完全限定它。
包也是利用多个离散功能单元来构造更复杂应用程序的不错方式。
要定义包,可使用 package
关键字,后跟一个合法的包名称,并以一个分号结尾。包名称常常遵循这种 事实 标准模式:
package orgType.orgName.appName.compName;
这个包定义可分解为:
orgType
是组织类型,比如com
、org
或net
。orgName
是组织的域名称,比如nowjava
、oracle
或ibm
。appName
是缩写的应用程序名称。compName
是组件的名称。
本课程将使用此约定,而且我推荐坚持使用它来定义包中的所有 Java 类。(Java 语言没有强制要求您遵循这种包约定。您完全不需要指定一个包,但在这种情况下,您的所有类必须具有唯一名称且将位于默认包中。)
Eclipse 使导入简化
在 Eclipse 编辑器中编写代码时,您可键入想要使用的类的名称,然后按 Ctrl+Shift+O。Eclipse 会确定您需要哪些导入语句并自动添加它们。如果 Eclipse 找到两个具有相同名称的类,它会询问您想为哪个类添加导入语句。
导入语句
类定义中的下一部分(返回参考清单 1 )是 导入语句 。导入语句告诉 Java 编译器在何处查找您在代码中引用的类。任何非简单的类都会使用其他类来实现某种功能,导入语句是您向 Java 编译器告知这些类的方式。
导入语句通常类似于:
import ClassNameToImport;
您指定 import
关键字,后跟您想要导入的类,然后输入一个分号。类名应是 完全限定的 ,意味着名称中应包含它的包。
要导入一个包中的所有类,您可将 .*
放在包名称后。例如,这条语句导入 com.nowjava
包中的每个类:
import com.nowjava.*;
但是,导入整个包会降低代码的可读性,所以我推荐使用完全限定名称来仅导入需要的类。
类声明
要在 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
值包括:
公共变量
使用公共变量绝不是一个好主意,但在极少的情况下有必要这么做,所以存在这个选项。Java 平台不会限制您的使用情形,所以需要您自己遵守使用良好的编码约定的纪律,即使您被诱惑不这么做。
public
:任何包中的任何对象都能看到该变量。(不要使用此值;请参阅 公共变量 边栏。)protected
:在同一个包中或(在任何包中定义的)一个子类中定义的任何对象都能看到此变量。- 没有修饰符(也称为 友好 或 包私有 访问):仅在同一个包中定义的类的对象能够看到此变量。
private
:只有包含该变量的类能够看到它。
变量的 dataType
取决于变量的类型 — 它可能是一种原语类型或另一种类类型(稍后将更详细地介绍)。
variableName
由您自己决定,但根据约定,变量名使用驼峰式大小写约定,但它们以小写字母开头。(这种样式有时称为 小驼峰式大小写 。)
现在暂时不要关心 initialValue
,只需知道可以在声明一个实例变量时初始化它。(否则,编译器会为您生成一个在实例化该类时设置的默认值。)
示例:Person 的类定义
这个示例总结了您目前所学的知识。清单 2 是 Person
的类定义。
清单 2. Person
的基类定义
package com.nowjava.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
构造方法是可选的
如果您不提供构造方法,编译器会为您提供一个,这个方法称为默认(或 无参数 或 no-arg)构造方法。如果您使用的构造方法不是 no-arg 构造方法,编译器不会自动为您生成一个。
argumentList
中的参数用逗号分隔,而且任何两个参数不能具有相同名称。argumentType
是一种原语类型或另一种类类型(与变量类型相同)。
包含构造方法的类定义
现在来看看在添加了通过两种方式创建 Person
对象的能力后会发生什么:通过使用 no-arg 构造方法和通过初始化一个部分属性列表。
清单 3 展示了如何创建构造方法,以及如何使用 argumentList
:
清单 3. 包含构造方法的 Person
类定义
package com.nowjava.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)
}
其他方法看起来非常像构造方法,但有两处例外。首先,您可为其他方法提供您喜欢的任何名称(但是,肯定要遵守某些规则)。我推荐以下约定: