Java面向对象程序设计(第三版)

上传人:阳*** 文档编号:93849442 上传时间:2022-05-21 格式:DOC 页数:33 大小:783KB
收藏 版权申诉 举报 下载
Java面向对象程序设计(第三版)_第1页
第1页 / 共33页
Java面向对象程序设计(第三版)_第2页
第2页 / 共33页
Java面向对象程序设计(第三版)_第3页
第3页 / 共33页
资源描述:

《Java面向对象程序设计(第三版)》由会员分享,可在线阅读,更多相关《Java面向对象程序设计(第三版)(33页珍藏版)》请在装配图网上搜索。

1、第1章 Java程序设计与开发1.1 概 述本章介绍Java程序设计与开发中需要用到的一些基本概念和技术。首先从确定设计面对对象程序的主要步骤开头。通过设计一个“提问”和“回答”的猜谜程序来阐述这些步骤。作为一个猜谜的例子,想一想“什么是黑和白并且可以读的?”的问题,答案当然是 报纸。在设计阶段之后,我们重点关注编写Java程序所需的步骤,这些步骤包括了编辑、编译和运行程序。由于有两种不同形式的Java程序应用程序(application)与小应用程 序(applet),所以我们将讲解编写这两类程序的不同之处。接下来,我们通过商量PrintStream和System类来生疏Java的扩展类库。

2、使用这些类包含的对象和方法即可实现在程序中打印输出。在本章结束时,你将能设计并编写出一个能“唱”你最喜爱的歌的Java应用程序。1.2 设计优秀的程序编程并不仅仅只是简洁地键入Java代码,而是需要进行大量的细心规划和设计。设计糟糕的程序几乎不行能正确运行。对于新手程序员来说,立刻开头编码是特别有诱惑力的,下面给出程序设计的首要规章之一。Java编程提示:越早开始编码,完成程序所需的时间就越长。在编码之前必须进行精心的设计,对于面向对象的程序来说,尤其如此。换句话说,设计程序时投入的思考和注意力越多,就越有可能得到一个可以正确运行的程序。下面这些小节将对程序开发过程做一个简要的说明。软件工程生

3、命周期软件工程是指设计和实现软件的过程。软件生命周期指的是在设计和开发一个计算机程序时所经历的不同阶段。本书所举的例子将集中商量整个生命周期的4个阶段。在分析阶段,我们供应了对某个问题的综述并简略说明白这个程序将要完成什么功能。在设计阶段,我们对程序中将要使用的各种各样的类、方法以及数据进行简略的说明。实现阶段指的是编写Java程序源代码的过程。在测试阶段,我们将测试程序的运行性能以确保它是正确的,如果有必要,将重新设计或编写这个程序。图1.1对程序开发过程做了更简略的介绍,主要集中在软件生命周期的设计阶段。它表明设计一个面对对象的程序是对组成程序的各种类、数据和方法提出正确问题的过程。总之,

4、程序开发过程可以看作是一个反复应用分而治之原则的过程,由于大多数编程问题可以反复分解,直到成为很多相对容易解决的子问题,每一个子问题对应于一个对象。通过使用这种方法,一个程序可以分解成一组相互作用的对象,然后再为每一个对象设计一个类。在设计类的时候,每个对象进一步分解成只包含属于它自己的变量和方法。图1.1 程序开发过程一览什么时候停止进一步的分解呢?一个对象或者方法应该安排多少个任务?要回答类似的问题并不容易。好的答案来自于丰富阅历所产生的良好推断力,而且好的解决方案常常不止一个。再次强调,随着我们学会更多关于面对对象设计的知识,我们也将学会如何更好地做出设计决策。1.3 设计一个猜谜程序程

5、序开发过程中的第一步就是确保你知道需要解决哪些问题(图1.1)。因此,我们从制定简略的规章开头,这将解决以下3个基本问题:l 到底要解决什么问题?l 程序将如何使用?l 程序将表现出哪些行为?在现实世界中,问题分析常常开头于开发者与客户深化商量之后。在程序设计入门课程中,这种分析通常由老师给出。为了让这种思路更清晰,我们来为这个简洁的问题设计一个面对对象的解决方案。问题规范:设计一个类来表示一个带有问题和答案的谜语。这个类的定义应使它可存储不同的谜语,并能够分别获得谜语的问题和答案。1.3.1 问题分解大多数问题都由于太大、太简单而不能一次性解决掉。因此,设计过程的下一步就是将问题分解成多个部

6、分,这样可以更好地管理其解决方案。在面对对象的方法中,一个问题被分解成多个对象,每个对象只处理本程序整体任务中的一个特定方面。这样,每个对象就成为程序的整体行为中某一方面的内行或专家。注意,在对一个给定的程序进行分解时,到底要分解到哪一步并不明确。这种不确定性源于过程设计本身。在一个程序的全部部分变得“简洁到可以解决”之前,我们要把它分解到什么程度?这取决于试图解决的问题和解决问题的人。下面是一条有用的设计指导原则,可以用来决定在程序中需要哪些对象。高效设计:寻找名词。选择程序的对象通常就是寻找问题分析中的名词。同样,这条指导性原则也存在不确定性。例如,当前问题中的关键词是谜语,所以解解决方案

7、中包含一个作为谜语模型的对象。这个Java对象的主要任务是表示一个谜语。问题分析中的另两个名词是“问题”和“答案”。幸运的是,Java带有内置的String对象,它用来表示一个字符串,如一个单词或句子。我们可以用两个String对象来代表谜语的问题和答案。因此,对于这个简洁问题,我们只需要设计一个新类型的对象,即谜语,其主要目的是表示谜语的问题和答案。如果觉得设计决策在这个阶段显得很神奇,不用担心。只有具备丰富的设计阅历之后,才能很好地理解面对对象设计,但这是一个好的起点。1.3.2 对象设计一旦把一个问题分解成一组相互协作的对象后,设计Java程序主要就是设计和创建这些对象本身。这意味着在这

8、个实例中,我们必须设计谜语对象的特征。对于每个对象,必须回答下面这些基本设计问题:l 对象在程序中扮演什么角色?l 对象需要什么数据或信息?l 对象将执行什么行为?l 对象为其他对象供应什么接口?l 对象向其他对象隐藏了哪些信息?就谜语对象来说,这些问题的答案在图1.2中给出。注意,虽然我们说“设计一个对象”,但实际上是在设计对象的类,一个类定义了属于它的对象集合。类可以看作是对象的类型,这与真实世界的对象一样。这样,seabiscuit(世界上速度最快的纯种马之一译者注)是马,也就是说,seabiscuit是马类型的一个对象。类似地,一个单独的谜语,例如报纸谜语,是个谜语,也就是说它是谜语类

9、型的一个对象。l 类名:Riddlel 角色:存储、猎取问题、答案l 属性:(信息)- question:用来存储谜语问题的变量(private)- answer:用来存储谜语答案的变量private)l 行为- Riddle():用来设置谜语问题和答案的方法- getQuestion():用来猎取谜语问题的方法- getAnswer():用来猎取谜语答案的方法图1.2 谜语类的设计分析下面的商量表示了怎样得到如图1.2所示的Riddle类的设计分析。Riddle对象的作用是建立一般谜语的模型。由于一个谜语是依据它的问题和答案来定义的,所以Riddle对象需要用某种方式来保存这两条信息。正如我

10、们在第0章所学,实例变量(instance variable)属于一个对象的命名内存区域。这样,通过调用变量的名字就能很容易地猎取所存储的数据。例如,为打印谜语问题,我们可以说“print question”,这样,存储在问题中的内容就会被猎取并被打印出来。通常,实例变量用来保存对象在完成其任务所需的信息。它们与我们前面所说的对象属性相对应。确定这些变量相当于回答这样一个问题:这个对象需要什么信息?接着决定一个谜语对象要执行什么动作。下面给出另一个有用的指导原则。高效设计:寻找动词。选取对象的行为往往是在问题分析的过程中寻找动词。就这个问题而言,关键的动词是赋值和猎取。如图1.2所表示的,每个

11、Riddle对象应该供应能对问题和答案的变量进行赋值的方法,分别猎取变量值的方法。每个已经确定的动作都将封装在一个Java方法里。在第0章中曾讲过,方法(method)是一段命名的代码,可以调用它来执行特定的动作。在面对对象的方法中,方法调用是不同对象之间进行交互的方式。调用一个方法就像在对象之间传递信息,例如,当我们想要得到谜语的答案时,就会调用getAnswer()方法。这类似于发出一个信息“给我答案”。当一个对象被创建时,一个称为构造函数的方法会被自动调用。我们将用这个构造函数Riddle()来对谜语的问题和答案赋初值。在设计对象时,必须确定哪些方法可以被其他对象调用。这就决定了对象要供

12、应什么样的接口,而对其他对象又应该隐藏什么信息。一般来说,用于和对象通信的方法被指定为对象接口的一部分。除了它的接口以外,每个谜语所维护的全部其他信息均应对其他对象保持隐藏状态。例如,其他对象没有必要知道一个谜语对象如何存储问题和答案。存储问题和答案的变量命名为question与answer,而不是ques与ans,这一点与其他对象无关。高效设计:对象接口。对象的接口应该包括与对象通信所需的方法或使用对象的方法。 高效设计:信息隐藏。对象应该隐藏其实现的大部分细节。综上所述,依据这些不同的设计决策而得出的分析结果如图1.3所示。如我们的商量所阐明的那样,通过恰当地提出并解答问题来形成决策。在大

13、多数情况下,属性(变量)是私有的,在它们的前面用一个减号(-)来表明。在这个例子里,操作(方法)是公共的,在它们的前面用一个加号(+)来表明。此图表示Riddle类有两个隐藏的(或私有的)变量用于保存数据,还有三个可见的(或公共)方法用于表示它能执行的操作。图1.3 表示Riddle类的UML类图1.3.3 数据、方法与算法完成谜语对象的需求分析之后,下一步是确定所需的数据、方法和算法。这需要回答下面两个基本问题。l 需要用哪种类型的数据来表示谜语所需的信息?l 每个方法怎样执行指定的任务?与其他程序设计语言类似,Java供应了丰富的数据类型,有些很简洁,有些很简单。显然,谜语的问题和答案应该

14、用文本类型来表示。正如我们前面所提到的,Java的String类型设计用来存储文本,它也可以用来表示字符串。在实现一个方法时,必须决定该方法要做什么。为了执行它的任务,一个方法需要某些保存在变量里的信息。另外,它还必须按挨次执行一系列活动来完成任务。这称为算法,它是对逐步解决问题的过程的描述。最后,必须确定该方法会产生什么结果。因此,在设计对象时,正确解决下面这些问题将特别重要:l 这个方法简略完成什么任务?l 它完成任务需要什么信息?l 它将使用什么算法?l 它会产生什么结果?方法可以看作是使用一种算法来完成所要求的行为。构造函数Riddle()所需的算法虽然很简洁,但对于很多类的构造函数而

15、言,它是很典型的。它使用了两个字符串,并把第一个赋给实例变量question, 把其次个赋给实例变量answer。Riddle类的其他两个方法所用的算法更简洁,它们称为“get”方法,仅仅是返回或产生当前保存在实例变量中的数据。并不是全部的方法设计起来都这么简洁,也不是全部的算法都这么浅显易懂。甚至在设计一个简洁的数学问题的程序时,它的算法所需的步骤并不总像手工计算时那样明显。例如,假设有一个求一组数字的和的问题。我们可以说,“把全部的数加起来并报告它们的总和”。但是,这种描述要用在程序中就显得模糊不清。作为对比,下面给出了一个程序可能使用的算法。1. 将总和(sum)初始化为0。2. 如果没

16、有更多的数字要累加,转到第5步。3. 将下一个数加到总和(sum)中。4. 转到第2步。5. 报告总和。这个算法中的每一步都很简洁而且容易实现。把它翻译成Java语言比较容易。由于用英语来描述算法总是不那么精确,程序员常常用伪码(pseudocode)或直接用程序设计语言来写算法。伪码是一种结合英语与程序设计语言的结构的混合语言,它没有程序设计语言那样琐碎的语法。例如,前面的算法可以用伪码表示如下:sum = 0while (more numbers remain) add next number to sumprint the sum当然,一个有阅历的程序员不行能花时间为这么简洁的程序写伪码

17、,但很多程序设计问题特别简单,需要细心设计,以尽可能削减程序中包含的错误。在这种情况下,伪码就显得特别有用了。算法设计的另一部分工作是用一些抽样数据来跟踪它的执行过程。例如,我们可以用下面的一组数据来跟踪数列求和算法的执行过程,以便对它进行测试。总和数列 0 54 8410454 30 20 30 20 20 起初,总和为0而数列中有54,30和20这些数字。在算法的每次循环中,总和逐个添加下一个数字的值,而数列中的数字个数削减。这样,算法终止时就可得到总和的正确结果。虽然这次跟踪没有发现任何错误,但用这种方法来跟踪算法的执行过程时极可能发现错误。1.3.4 用Java编写代码一旦完成足够简略

18、的设计,就可以开头编写Java代码了。立即输入整个程序,然后编译并运行,这种做法是错误的,这通常会导致很多难以改正且令人懊丧的错误。正确的编码方法是接受逐步求精(stepwise refinement)的原则,把程序分成若干小段来编写,每完成一小段就编译并测试它。例如,你可以先写出一个方法并测试它,然后再写程序中其他的部分。用这种方法,在连续下一步之前可以把那些小错误找出来。Riddle类的代码如图1.4所示。即使我们还没有开头学习Java语言的细节,也可以轻松地找出程序的关键部分:String类型的实例变量question与answer,用来保存谜语的数据;Riddle()是构造函数,get

19、Question()和getAnswer()方法组成了它的接口。本章和下一章将介绍理解这些内容所需要的相关语言细节。/ * * File: Riddle.java * Author: Java, Java, Java * Description: Defines a simple riddle. * /public class Riddle extends Object / Class header / Begin class body private String question; / Instance variables private String answer; public Rid

20、dle(String q, String a) / Constructor method question = q; answer = a; / Riddle() public String getQuestion() / Instance method return question; / getQuestion() public String getAnswer() / Instance method return answer; / getAnswer() / Riddle class / End class body图1.4 Riddle类的定义1.3.5 语法和语义要编写Java代码

21、,需要知道它的语法和语义。语言的语法(syntax)是推断特定语句的格式是否正确的一套规章。举一个说明语法规章的例子,看一看下面两句话:The rain in Spain falls mainly on the plain. / ValidSpain rain the mainly in on the falls plain. / Invalid第一句话遵循英语语法的规章,它的意思是西班牙平原下了很多雨。其次句话没有遵循英语语法,因此,它表达不了任何意义。Java语法规章的一个例子是每个Java语句都必须以分号结束。在英语中,即使违反语法规章,别人仍然可以理解你,但是在编程语言中,语法规章特别

22、严格。可能你只违反了一条很小的语法规章,例如,忘了一个分号,程序也不会运行。类似地,程序员必须知道语言的语义,即每条语句的意思。在程序设计语言中,语句的含义取决于它将对程序产生什么影响。例如,在前面的算法中,要把sum初始化为0,就需要用一条赋值语句来把0值存储到名为sum的特定内存区域内。因此,我们说以下 语句:sum = 0;把0值赋给特定内存区域sum,它将保存在那里,直到程序中的其他部分需要它。学习Java的语法与语义是学习程序设计的主要内容。在这方面,学习编程与学习外语特别相像。越快学会并娴熟地使用新语言(Java),就能把那些有味的程序设计问题的解答表达得越好。在掌握Java的规章

23、和惯例方面花的时间越多,你就越难用一种一般的语言表达清晰一个问题。还有,计算机对语言正确性的要求比人类苛刻得多,即使是最小的语法错误或语义错误也可能导致巨大的失误。因此,要尽最大努力特别精确地掌握Java的语法与语义。1.3.6 测试、调试与修改编写、测试与修改程序是一个循环反复的过程,这就要求你不断重复图1.1所示的程序开发过程中的不同阶段。依据逐步求精的原则,该过程应该按小增量步骤进行开发,这样,每一步结束后,问题的解答就会变得更细化一点。然而,无论多么当心,在编码过程中还是可能出错。语法错误是违反Java语法规章的错误。Java编译器可以查出代码中的任何语法错误,一旦明白了编译器给出的错

24、误信息,改正语法错误就相对容易一些。只要程序还有语法错误,程序员就必须改正它们并重新编译。如果全部的错误都被改正了,编译器将产生一个可以运行的可执行文件。在程序运行时,计算机按程序指定的步骤执行并产生结果。然而,一个程序能运行并不意味着它能工作并可以得到正确的结果。一个可运行的程序有可能包含语义错误(semantic error),也叫规律错误(logical error),语义错误是由程序规律设计中的错误引起的,它使程序不能正确运行,产生的结果也不正确。与语法错误不同,语义错误无法自动检测。例如,假设一个程序包含下面用来计算矩形面积的语句:return length + width;由于我们

25、把长与宽相加而不是相乘,得到的结果肯定是不正确的。但是表达式length+width没有任何语法错误,所以编译器不会检测到这条语句里的错误。这样,计算机将执行这条语句并计算出不正确的面积结果。语义错误只能通过测试程序来发现,而且有时它们是特别难以检测的。由于在一个测试中程序能正常运行并不能保证程序中不存在语义错误。一个程序看起来能够正常运行,可能只是由于它还没有经过足够多的测试。检测到语义错误时,必须找出它们并进行改正,程序设计的这个阶段称为调试。消失细微的错误时,程序调试是整个程序设计过程中最令人头疼的阶段。本书供应的各种各样的实验练习将给出如何查找代码中的bug的提示与建议。在查找这些细微

26、的缺陷时,要牢记一点,不管你多么信任自己的代码是正确的,多么确信那个bug是计算机的某种错误引起的,几乎都可以肯定那个错误是由代码所引起的。Grace Hopper和第一只计算机bug海军少将Grace Hopper(19061992)是一位计算机程序员先驱,并且是COBOL程序设计语言最初的开发者之一,COBOL代表通用的面对商业语言。除了她的成就和声望之外,Hopper少将还制造了computer bug这一术语。1945年8月,她和其他的一些程序员正在Mark I上工作,Mark I是在哈佛高校开发的计算机,是现代电子计算机的祖先之一。为了找出计算机的故障,他们经过几个小时的努力,终究有

27、人在一块计算机电路上找到并移去一只两英寸大小的蛾子。从那时起,任何时候计算机出错,Hopper少将和其他人就会说“有bug”。第一只bug还记录在 Hopper少将1945年的日志簿里,现保藏于海军水面武器中心。1991年,布什总统授予Hopper少将国家科技勋章。为了纪念和表彰Hopper少将的很多贡献,美国海军最近以她的名字命名一艘军舰。有关Hopper少将的更多信息,请登录网站。1.3.7 编写易读的程序成为一个娴熟的程序员远不只是写出能得到正确输出的程序那么简洁,还包括形成良好的编程风格,即对你和其他人来说代码的可读性和可理解性如何。我们的目标是形成满足下面这些原则的编程风格。l 可读

28、性。程序应该容易阅读和理解。应该用注释来说明程序代码并形成文档。l 清晰性。程序应该用大家熟知的结构与标准的约定,而且应该避开在程序设计方面耍小聪慧,避开编写模棱两可或是异常简单的代码。l 敏捷性。程序应该细心设计并编写,使其易于维护和修改。1.4 Java语言元素在这一节中,我们将通过描述一个小程序的细节来介绍Java语言的一些关键元素。我们将介绍程序是如何组织的,各部分有何用途。我们的目的是介绍重要的语言元素,后续小节将特别简略地讲解这其中的很多语言元素。我们将要学习的程序是Java版的经典HelloWorld程序。之所以称之为经典,是由于几乎每个编程入门教材都是从它开头的。运行时,Hel

29、loWorld程序(图1.5)将在掌握台屏幕上显示“Hello World”的欢迎词。/ * * File: HelloWorld.java * Author: Java Java Java * Description: Prints Hello World greeting. * / public class HelloWorld extends Object/ Class header / Start class body private String greeting = Hello World!; public void greet() / Method definition / St

30、art method body System.out.println(greeting); / Output statement / greet() / End method body public static void main(String args)/ Method header HelloWorld helloworld; / declare helloworld = new HelloWorld(); / create helloworld.greet(); / Method call / main() / HelloWorld class / End class body图1.5

31、 HelloWorld应用程序1.4.1 注释关于HelloWorld程序,第一个需要注意的是注释的使用。注释是用于建立程序文档的非执行部分,由于注释是非执行语句,编译器将会忽视它,使用它的唯一目的是使程序更易于阅读和理解。HelloWorld程序有两种形式的Java注释。在*与*之间的任何文本都被当作注释,在HelloWorld程序中,这种注释可以延长至很多行,有时称作多行注释。其次种注释是双斜线(/)后的任何文本,由于它不能超过一行,所以称为单行注释。编译器遇到多行注释的开头/*时,它将忽视一切代码,直到找到对应的结束标志*/。这表明不能把一个多行注释放在另一个多行注释内。也就是说,注释不

32、行以嵌套。下面的代码段解释了使用/*和*/的规章。/* This first comment begins and ends on the same line. */* A second comment starts on this line . and goes on . and this is the last line of the second comment.*/* A third comment starts on this line . /* This is NOT a fourth comment. It is just part of the third comment. A

33、nd this is the last line of the third comment.*/*/ This is an error because it is an unmatched end marker.从这个例子可以看出,在一个已经开头的注释里面,不行以再开头一个新的注释。这是由于在第一个注释里的文本,包括“/*”都会被编译器忽视。Java语言规则注释。多行注释以“/*”开始并以“*/”结束,可以延伸至很多行。编译器将会忽略它。注释双斜线(/)可用于把任意一行或该行的后面部分变成单行注释。多行注释常用于生成注释块来供应有用的程序文档。在HelloWorld中,程序以一个注释块开头,用

34、于给出程序名、作者名以及程序所做事情的简要说明。对于单行注释,双斜线(/)可以加在一行的任何地方,其后的部分将被编译器忽视。HelloWorld程序使用了很多单行注释来注释语言元素。Java编程提示:注释的使用。编写良好的程序在开始处应该有一个注释块,用于给出程序名、作者名以及程序所做事情的简要说明。1.4.2 程序布局另一个需要注意的事情是如何将程序整齐地排列在页面上。这是为了让程序易读、好懂而有意这样做的。在Java中,程序表达式和语句可以由程序员任意支配。它们可以每行一条、每行几条或一条占几行。正由于程序布局如此松散,所以养成良好的程序设计风格以使程序易读,就显得特别重要。充分利用程序元

35、素之间的空白有助于使程序更易读,也更具有吸引力。看一看HelloWorld中的语句是如何排列的。注意起始括号和结束括号是如何对齐的,如何使用单行注释符在结束括号后面加上注释。在Java程序中,使用大括号来标识不同的程序块,适当的缩进和单行注释会更容易推断大括号是如何配对的。类似地,可以使用缩进来表示程序的一个元素何时被包含在另一个元素中。这样,HelloWorld类的元素是在标识开头和结束的大括号内缩进的。在main()方法内的元素以缩进来表示它们是属于一个方法的,像这样使用缩进来分辨程序的结构会使程序更加易读、 好懂。Java编程提示:缩进的使用。一个块内的代码应该缩进。块的开始与结束括号应

36、该对齐。应该用一个注释来标识一块代码的结束。1.4.3 关键字和标识符如表1.1所示,Java有50个预定义的关键字,它们是语言中有特别意义的单词并被保留用于特别用途。例如,HelloWorld程序(图1.5)中所使用的关键字是:class,extends,private,public,static和void。表1.1 Java 关键字abstractcontinuefornewswitchassertdefaultgotopackagesynchronizedbooleandoifprivatethisbreakdoubleimplementsprotectedthrow 续表byteels

37、eimportpublicthrowscaseenuminstanceofreturntransientcatchextendintshorttrycharfinalinterfacestaticvoidclassfinallylongstrictfpvolatileconstfloatnativesuperwhile关键字的一个重要限制是它们不能作为方法、变量或类的名称。但是,在符合规章和约定的情况下,程序员可以为程序中的类、方法和变量命名。类、方法和变量的名称称为标识符,它们应该满足某些语法规章。Java语言规则标识符。标识符必须以字母(AZ,az)开头,后跟任意数目的字母、数字(09)或

38、下划线(_),或美元符号($)。标识符不能和Java关键字相同。记住,Java是区分大小写的,所以两个不同的标识符可能包含挨次相同的相同字母(如thisVar与ThisVar),它们只是第一个字母的大小写不同。除了标识符的语法规章外,Java程序员为类、变量和方法命名时应该遵循肯定的风格约定。类的名称应该以大写字母开头并且名称中的每个单词应以大写字母开头,例如HelloWorld和TextField。变量和方法的名称应以小写字母开头,但也可以大写字母开头来区分单词,例如main(),greeting,greet(),getQuestion()和getAnswer()。这个约定的优点是只要看看程

39、序中的元素是如何写的,就能很容易地区分它是类、方法、还是变量(想要了解更多的Java风格约定,请看附录A)。Java程序员应该遵循的另一个重要约定是可以使用描述性的标识符为类、变量和方法命名,使程序更易读。Java编程提示:标识符的选择。为了使程序更易读,最好使用能描述类、变量和方法用途的名称。1.4.4 数据类型和变量如果计算机程序不能操作不同类型的数据,例如数字和字符串,那么它的作用将大大受限。它能对数据进行什么样的操作取决于数据的类型,例如,可以对数字进行乘和除运算,但对字符串就不行。因此,Java程序中的数据是依据其数据类型来区分的。广泛地讲,Java中有两种类型的数据:各种对象类型和

40、8种自带的原子数据类型。除了程序员设计的新的对象类型外,Java还有很多种自带的对象类型。在这一章中,我们将遇到两种类型String和PrintStream。Java的原子类型包括3种整型类型、3种实型类型、1种字符类型和1种只有true和false值的布尔类型。原子类型的名称用关键词int表示整型,double表示实数型,boolean表示布尔类型。正如我们在第0章中所提到的,变量是一个有名称的存储位置,它用于存储一个特定类型的值。实际上,你可以把变量当作一个特别的用于保存数据的容器,但只保存某种类型的数据(如图1.6)。例如,一个int型变量可以保存如5或-100的数据。一个String型

41、变量可以保存如“Hello”这样的数据(实际上,这并不全对,而是有更简单的解释,我们将在第2章进行更多商量)。图1.6 变量就像有类型的容器在HelloWorld类中,实例变量greeting(第8行)保存了一个String类型的值。在main()方法中,变量helloworld被赋值给HelloWorld对象(第16行)。文本值是程序中的某些类型的实际值。例如,双引号中的字符串(如“Hello World!”)是一个String文本。一个数字(例如45.2)是double类型的字面值,-72是int类型的字面值。我们的HelloWorld程序只用到一个字符串字面值,即字符串“Hello Wo

42、rld!”。1.4.5 语句Java程序是语句的集合,语句是在程序中执行某种动作的代码段。当程序运行时,我们说它是在执行语句,意思是它在执行语句中的动作。在我们的HelloWorld程序中,第8,11,15,16和17行有各种类型的语句。注意,这些行都是以分号结束的,Java的规章是每条语句必须以分号结束,省略分号会造成语法错误。声明语句用于声明一个特定类型的变量。在Java中,变量在使用前必须先被声明,不声明会产生语法错误。在最简洁的情况下,一个声明语句通常以变量类型开头,接着是变量的名称,最后以分号结束。如下所示:类型 变量名;变量类型可以是我们提到的原子类型中的任意一种,例如int,do

43、uble或boolean,或者对于一个对象来说,它是对象的类的名称,例如String或HelloWorld。尽管Java约定变量的名称以小写字母开头,但如前所述,它可以是任何合法的标识符。在HelloWorld程序中,第15行有一个简洁的声明语句:HelloWorld helloworld;这个例子为一个对象声明白一个变量。变量名称是helloworld, 它的类型是HelloWorld, 它是我们例子中所定义的类的名称。又例如,下面的语句声明白两个int变量,分别取名为int1和int2:int int1;int int2;正如我们所提到的,int是Java的一个原子类型,单词int是Jav

44、a的关键字。这里不进行更多的细节描述,声明一个变量可以使程序留出足够的内存空间来保存这种类型的数据。因此,在这个例子中,Java将会保留足够的空间来保存一个int类型的数据。赋值语句是把一个值保存(或赋值)到一个变量中的语句。赋值语句使用等号(=)作为赋值操作符。其最简洁的形式是,等号的左边是一个变量,右边是某种类型的值。犹如别的语句,赋值语句以分号结束:变量名=数值;执行赋值语句时,Java将首先确定右边是何种类型的数值,然后把它赋值(保存)给左边的变量。这里有几个简洁的例子:greeting = Hello World;num1 = 50; / (a) Assign 50 to num1n

45、um2 = 10 + 15; / (b) Assign 25 to num2num1 = num2;/ (c) Copy num2s value (25) into num1第一个例子里,右边的值是字符串文本“Hello World”,它被保存于greeting中。当然,greeting必须是与右边相同的String 型变量。下一个例子中,右边的值是50。假设num1是int型的变量,它用于保存这个值。这个赋值过程如图1.7(a)所示。第3个例子中,右边的值是25,它是由10加上15所得到的。于是赋给num2的值是25。这个赋值过程如图1.7(b)所示。当然,这里假设num2是一个int变量。

46、最后一个例子中,右边的值是25,它是我们刚刚保存在变量num2中的值,于是25被保存于num1中,如图1.7(c)所示。图1.7 3个赋值过程(a),(b)和(c)中变量num1和num2的状态变化最后一个例子:num1 = num2; / Copy num2s value into num1这可能会使初学者感到困惑,因此需要进一步的阐述。在这个例子中,赋值操作符左右两边都是变量,但是它们的意义根本不同。右边的变量被当作数值,如果这个变量保存25,那么这就是它的值。实际上,赋值操作符右边的不论是什么,都会被当作数值。左边的变量被当作内存区域,它将保存此语句执行的结果25。此语句的效果是把num

47、2所保存的值复制在num1里,如图1.8所示。图1.8 在赋值语句 num1 = num2 中,num2的值被复制到num1中Java有很多其他类型的语句,我们将在下面的例子中学习。下面的例子来自HelloWorld程序,它将调用一个方法:System.out.println(greeting); / Call println() methodhelloworld.greet(); / Call greet() method 对于这些例子,我们将有更简略的叙述。到目前为止,需要提到的最后一种语句是复合语句(块) ,它是包含在大括号里的一组语句。HelloWorld程序中有3个这样的例子,从第7

48、行到第19行的类定义。greet()方法是一个从第10行到第12行的语句块,main()方法是一个从第14行到第19行的语句块。1.4.6 表达式和操作符通过使用指明操作的表达式可以处理程序中的数据。表达式用于在Java程序中指定或产生一个值,例如把两个数相加,可以使用算术表达式,如num1+num2。比较两个数,可以使用关系表达式,如num1num2。可以看出,这些表达式都使用了特别的符号,叫操作符。在这里,我们看到了加法操作符(+)、小于操作符()和前面提到的赋值操作符(=)。Java表达式和操作符的类型取决于它们所操作的数据。举个例子,两个int值相加,例如5+10,这个表达式会生成一个

49、int型的结果。用小于操作符比较两个数值时,这个表达式会生成一个boolean值:false或true。需要注意的是,表达式本身不能单独存在,它们只能作为语句的一部分而存在。这里还有使用表达式的一些其他例子:num = 7 / An assignment expression of type intnum = square(7) / An method call expression of type intnum = 7 / An equality expression of type boolean第一个是赋值表达式。由于它把7赋值给num,它的值是7。其次个也是赋值表达式,但是它在右边有一

50、个方法调用square(7)(我们假设方法square()已在程序中恰当定义)。方法调用是另一种表达式。这个例子中,它的值是49。注意,如果在赋值表达式后加一个分号,那么它就可以变成一个单独的赋值语句。第三个表达式是等值表达式。假设保存在左边的变量值是7,那么它的值是true。注意,赋值操作符(=)与等值操作符(=)之间的区分。Java语言规则相等与赋值。注意,不要把=和=混为一谈。符号=是赋值操作符,它把右边的值赋给左边的变量。符号=是等值操作符,它根据左右两边的表达式的值是否相等而相应地返回true或false。自测题1.1 执行下面两个语句后,变量num中会保存何值?int num =

51、11;num = 23 num;1.2 编写一个语句,令其声明一个 int类型的变量num2,并保存711与712的和。1.4.7 类定义一个Java程序可以包含一个或多个类定义。在HelloWorld例子中,定义了一个HelloWorld类,程序中还有3个预定义的类,分别是Object,String和System,它们已经在Java的类库里定义了。预定义的类可以用于任何程序。正如HelloWorld程序的注释所表示的那样,类定义包含有两部分:类的首部和类的主体。通常,类的首部有下列形式,有的是可选的(opt):类修饰符(可选)class类名祖先(可选)HelloWorld的首部是:publi

52、c class HelloWorld extends Object首部的作用是标识类的名称(HelloWorld),确定它的可访问性(public或private),描述它在Java类层次结构中的位置(作为Object类的扩展)。在这个例子中,首部是以可选的访问修饰符(access modifier)public开头,表示这个类可以被全部的类访问。下一部分表示类的名称:HelloWorld。最后一部分表示HelloWorld是Object类的子类,我们称这部分为类的 家谱。从第0章我们得知,Object类是Java类层次结构中处于最顶层的类。定义HelloWorld extends Objec

53、t,是指HelloWorld是Object的直接子类。实际上,不必这样清晰地定义 HelloWorld extends Object,由于这是Java的默认设定。这样,如果在类的首部省略extends Object部分,Java会默认为它是Object的子类。类的主体在一对花括号中,它包含组成类的对象的元素的声明和定义。同时,它也定义了类的属性和操作。1.4.8 声明一个实例变量类定义的主体通常由两部分构成:成员变量和成员方法。如第0章所述,实例变量是属于某个类的对象或实例的变量。那么,类的每一个实例都有自己的类的实例变量的副本。HelloWorld类有一个实例变量greeting,它的声明如

54、下:private String greeting = Hello World!;通常,实例变量的声明格式如下,有些部分是可选的:修饰符(可选)类型变量名初始化表达式(可选)实例变量的声明是从可选修饰符开头的。我们使用访问修饰符private来声明greeting, 这样,它就只属于HelloWorld类,不能被别的对象所直接访问。声明的下一部分是变量的类型。在这个例子里,greeting变量是String类型,这意味着它只能保存字符串对象。下一个是变量的名字,这里是greeting。这个名字用于指示类的变量在内存中的位置。例如,在第11行中,它用于println()语句中。声明的最后一部分是

55、可选的初始化表达式。在这个例子里,我们把“Hello World!”作为初始值赋值给greeting变量。1.4.9 定义实例方法方法是一段已命名的代码块,用来执行特定的任务。在Java类里,方法相当于对象的行为或操作。HelloWorld中定义了两个方法:greet()方法和main()方法。方法定义可以分为两个部分:方法头部和方法主体。通常,方法头部有下列的形式,有些部分是可选的:修饰符(可选)返回类型方法名(参数列表(可选)和变量的声明一样,实例方法也是以可选修饰符开头的。例如,第9行的greet()方法中使用了访问修饰符public,表示这个方法可以被全部其他类访问。第13行定义的ma

56、in()方法是一个特别的方法,我们将在下面解释。接下来是方法的返回类型。如果这个方法有返回值,它将表示返回值的类型。这两种方法的返回值类型都是void,表示它们都没有返回值,void方法只是执行主体内的语句序列。Riddle类的getQuestion()方法有返回值,它返回一个String值。返回类型后面是方法的名字。它是方法调用时所用的名字。例如,在第17行中,greet()方法被调用。紧跟在方法名字后的是方法的参数列表。当方法被调用时,参数用来临时保存传递给方法的数据变量。有些方法不用参数,例如greet(),由于它们不需要传递任何信息。Riddle()构造函数则使用了参数,它包含代表谜语

57、的问题和答案的参数(图1.4)。方法定义的最后一部分是它的主体,它包含一系列的可执行语句。可执行语句就是一条Java语句,程序运行时它将进行一些操作。例如greet()方法中的语句:System.out.println(greeting); / Output statement此语句表示在掌握台屏幕上打印一个欢迎词。1.4.10 Java应用程序HelloWorld是Java应用程序的一个例子。应用程序是“独立”的,这里的意思是说,它不需要依靠于别的程序(例如扫瞄器),可以独立执行。每个Java应用程序必须包含一个main()方法,它是程序执行的起点。对于一个包含了几个类的程序,由程序员来确定

58、哪个类包含main()方法。对于HelloWorld程序,我们不必担心如何确定,由于它只有一个类。由于main()方法作为Java应用程序的入口函数而具有独特性,所以它的首部必须声明如下:public static void main(String args)它必须声明为public,这样它才可以被外部访问。修饰符static表明main()是类的方法。第0章提到类的方法只与类本身相关,与类的对象无关。类的方法不是类的对象的一部分。实例方法是通过类的对象来调用的,而类的方法是通过类本身来调用的。这样,在类的对象生成之前,类的方法就可以被调用。作为程序执行的起点,main()必须是类的方法,由于

59、在程序生成对象之前,Java运行时的系统会首先调用main()。方法main()的返回类型是void,这意味着它不返回任何值。最后,注意main()的参数列表包含一个名为args的String参数的声明。它是程序运行时传送String类型参数的数组,详情参见第9章。1.4.11 生成和使用对象HelloWorld程序在main()方法的主体中生成它的唯一对象。当它运行时,程序只是打印出“Hello World!” 的欢迎词。如我们前面所提到的,这个操作是在greet()方法内发生的。所以,为了让这个操作发生,我们需要调用greet()方法。由于greet()是一个属于HelloWorld对象的

60、实例方法,我们必须首先生成一个HelloWorld的实例。这些都发生在main()方法的主体之内(如图1.5所示)。main()方法有3个语句:HelloWorld helloworld; / Variable declarationhelloworld = new HelloWorld(); / Object instantiationhelloworld.greet(); / Method invocation第一个语句声明白一个HelloWorld类型的变量,再把一个HelloWorld对象赋值给它。其次个语句生成一个HelloWorld对象。这是通过调用HelloWorld()构造函数来实现的。生成一个对象的过程称为对象实例化,由于生成了一个对象的实例。一旦HelloWorld的实例生成了,我们就可以使用它的实例方法来执行一些任务或操作。于是,在第三个语句中,我们调用了greet()方法,它将在掌握台屏幕上打印出“Hello World!”。如果回头查看图1.5中的HelloWorld程序,并不能看到一个构造函数的定义。这不是一个错误,由于,如果类本身没有包含一个构造函数,那么Java将自动产生一个默认的构造函数,默认的构造函数将不包含任何语句。下面是默认的HelloWorld的构造函数:public

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!