我们前面提到,Java中以面向对象的方式来模拟现实世界。那么,在Java中模拟对象,首先需要考虑的就是如何创建对象,也由此引发了类的概念的提出。
2.2.1 对象构成的计算机世界——程序
计算机从诞生,就开始逐步应用到我们生活的各个方面。例如,它可以帮我们记录仓库库存、计算收支情况。甚至,我们可以在虚拟世界中交朋友、做生意。俨然计算机为我们构建一个新的世界。而计算机靠什么完成的?那就是程序。程序将我们的现实世界进行模拟,然后从而构成一个新世界。
为了便于模拟,Java程序采用了对象的方式。对应于现实世界,需要什么对象,就在程序中模拟什么对象。例如,咖啡屋中有5个服务员,那么就可以利用程序来创建5个对象来模拟这5个服务员。这种分析问题的方式,被称为面向对象设计。Java语言就是这样一种面向对象语言。
2.2.2 程序从类开始
现实世界中,所有的东西都是客观存在的。但是对于程序构成的计算机世界却刚好相反。刚开始写程序的时候,一切都是空白。每个人程序员都需要像上帝一样创造自己的世界。那我们该如何进行创世呢?现在,我们思考一下,在现实世界中如何创造一个全新咖啡杯的过程。
首先,在制造之前,设计者需要考虑基本框架。这主要包括两大方面的内容,一是咖啡杯的样式、图案等属性,二是咖啡杯所应具备的功能。当明确了咖啡杯的各项属性和所需功能之后,便可以制作一个咖啡杯模型;接着,获得适量的原材料,利用模型来制造出一个新的咖啡杯。
对应于Java中,程序员首先要思考要模拟的对象是什么样子,这里也包含两方面的内容——类的属性(也就是我们常说的成员变量)和类的方法(对应于类所需要实现的功能,即类的成员方法);当完成设计之后,就可以创建一个Java类(相当于咖啡杯模型);接着利用类创建一个新的对象。
这里有一个很重要的问题就是,现实世界中的对象是实实在在存在的。但是,每个人对同一类对象的感知和认识可能会有着这样那样的差异。程序员也不例外,因此,当程序员利用面向对象的方式来思考和模拟现实世界时,他们所写出的程序也会存在差异。例如,针对咖啡杯而设计的类,该类包含多个属性:
-
咖啡杯的属性——大小,有的程序员定义为“大小”,而有的程序员定义为“尺寸”
-
咖啡杯的属性——价格,有的程序员使用了“价格”这个名字,而有的程序员可能更倾向于“售价”这个词
虽然有差异,但是无论哪种设计都是正确的。当然,允许差异的同时,也应该保持对原有对象的准确描述。这里的准确应该遵循的一个基本原则是,保持通用性,让其它的程序员非常容易理解,并且不会产生歧义。
2.2.3 制作模型——类
类的创建需要以软件需求的事物为原型进行概括和抽象。这里的事物不仅包含了看得见摸得着的对象,而且包含存在人们意识中的想法等。例如,咖啡杯对象,可以抽象出咖啡杯类;咖啡的配方也可以抽象出一个类。
在Java中定义一个类,应该利用class关键字。我们首先来尝试创建一个模拟咖啡杯的类——CoffeeCup。
【示例2-1】利用class关键字创建一个最基本的Java类
class CoffeeCup {
}
其中,class用于声明一个类,CoffeeCup则是类的名字;大括号内部是类的定义——此处为空,代表该类尚未进行任何描述。如同说,这是一个模型,只是模型还有改进的空间。
2.2.4 Java中的单词——关键字和标识符
在上一个小节中的class和CoffeeCup都是构成程序的基本元素。在汉语中,这样的内容被称为词语;而在编程语言中,被称作词(Word)。具体到Java中,它们分别被称为关键字和标识符。事实上,class是一个关键字,用来声明一个类;而CoffeeCup则是一个标识符,用来表示类的名字。那么,Java在编译和运行时,是如何知道将class视作类的声明,而将CoffeeCup视作类的名字呢?
让我们站到编程语言设计者的角度来思考这个问题。所有编程语言所编写出的程序代码,都是由一个个单词组成的。并且,这些单词可以被编译器解释为一条条指令。通过执行这些指令来完成开发者的意图。对于Java来说,是通过Java编译器来解释这些指令的。这就涉及到以下3个问题:
-
Java必须内置一些固定指令。这些固定指令,Java编译器可以解释为特定的动作。例如,“走”这个动作,就是一种固定的指令,无论是张三接到“走”这个指令,还是李四接到,都知道如何行动。
-
Java的内置指令必须足够开发者完成几乎所有能想到的任何事情。否则,Java语言本身设计便存在瑕疵。任何一门编程语言都不会犯下这样的错误——因为指令的缺失,无法满足客户的需求。
-
这些内置的指令不能够被用户随意的使用,例如作为自定义的名称。如果客户在非法的地方使用了内置指令,那么编译器应该给出错误提示。
Java通过关键字机制来解决这3个问题。首先,关键字被Java内置和界定,从而可以被Java编译器解释;其次,关键字的使用遵循一定的规则,这样,保证了编译器解释时不会出现混乱。
Java中共有49个关键字,如表2-1所示。
表2-1 Java中的关键字
abstract | break | boolean | catch | case |
case | class | char | continue | default |
double | do | else | extends | false |
final | float | for | finally | if |
import | implements | int | interface | instanceof |
long | length | native | new | null |
package | private | protected | public | return |
switch | synchronized | short | static | super |
try | True | this | throw | throws |
threadsafe | transient | void | while |
除关键字之外,Java中还含有几个保留字。保留字是指,目前并未被用作关键字,但是在今后的升级版本中可能会作为关键字。保留字同样不能被开发者随意使用。到目前为止,Java中的保留字只有两个,如表2-2所示。
表2-2 Java中的保留字
Const | goto |
一段Java程序,除了Java指令之外,还需要指令的作用目标。Java指令的作用目标,可以利用标识符来进行标识。标识符的构成规范如下:
-
标识符不能是关键字和保留字。
-
标识符不能以数字开头。如果允许以数字开头,编译器就无法区分标识符与普通数字了。
-
标识符可以是任意字母、数字、下划线和美元符号的组合。其实,这里的任意字母是指Unicode字符集的任意字符。当然,也包括汉字,例如,
public class 张三 {} // 使用了汉字“张三”作为标识符的类
-
尽量避免使用英文之外的其他语种的字符来构造标识符,即使不会出现语法错误。使用非英文字符作为标识符,将给程序带来很多隐患。例如,程序员可能根本无法理解别国语言写的代码;或者,他们所使用的开发工具根本不支持程序所使用的特殊字符集,那么所看到的程序将是一堆乱码。
-
标识符是区分大小写的,例如,VALUE和Value是两个不同的标识符。
-
类名是最常见的标识符。一个命名良好的类名,还应遵循以下规则:
-
类名由一个或多个单词组成,类名应该能准确表达该类所代表的事物。
-
每个单词的首字母必须大写,以便区分每个单词。
-
对于多个单词组成的很长的类名,可以考虑使用单词缩写,但是缩写形式必须足够通用。
-
宁可选择长而明确的类名,也不选择简短但不能明确表达意义的类名。
更多技术交流文章,请关注微信公众号【时代码农】