书名:21天学通Java(第7版)
ISBN:978-7-115-43534-7
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
• 著 [美] Rogers Cadenhead
译 袁国忠
责任编辑 傅道坤
• 人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
• 读者服务热线:(010)81055410
反盗版热线:(010)81055315
Rogers Cadenhead: Sams Teach Yourself Java in 21 Days(7th Edition)
ISBN: 067233710X
Copyright © 2016 by Pearson Education, Inc.
Authorized translation from the English languages edition published by Pearson Education, Inc.
All rights reserved.
本书中文简体字版由美国Pearson公司授权人民邮电出版社出版。未经出版者书面许可,对本书任何部分不得以任何方式复制或抄袭。
版权所有,侵权必究。
本书是初学者学习Java编程语言的畅销经典教程,循序渐进地介绍了Java编程语言知识,并提供了丰富的实例和练习;同时全面涵盖了Java 8这一新标准以及与Android开发相关的Java编程知识。通过本书的学习,读者将逐步了解、熟悉并精通Java编程语言。
本书包括3周的课程,通过学习,读者将具备使用Java开发应用程序和Android应用的知识和技能。第1周介绍Java语言的基本知识,包括数据类型、变量、表达式、对象、数组、条件语句、循环、类、接口、包、异常、线程等;第2周介绍Java类库,包括链表、栈、散列映射和位组等数据结构以及Swing组件、布局管理器和Java Web Start等;第3周介绍高级主题,包括输入和输出、内部类和闭包、通过Internet进行通信、使用数据库、XML、Web服务、Android编程等内容。
本书可作为初学者学习Java编程技术的教程,也可供已掌握其他语言的程序员学习Java时参考。
Rogers Cadenhead是程序员兼作者,出版了30多部编程和Web发布方面的著作,其中包括Sams Teach Yourself Java 2 in 24 Hours和Absolute Beginner’s Guide to Minecraft Mods Programming。他还是Drudge Retort等网站的发布人,这些网站每年的访问量超过2000万。他还维护着本书配套网站www.java21days.com及个人博客http://workbench.cadenhead.org。
献给刚进入艺术学校学习的儿子Max Cadenhead。你年纪轻轻,却才华横溢,对艺术孜孜以求,真让我自豪!
像本书这样涉及范围广泛的图书能够得以出版,有赖于很多人的辛勤劳动与奉献,这些人大多是位于印第安纳波利斯的Sams出版社的工作人员,他们是Boris Minkin、Barbara Hacha、Elaine Wiley和Mark Taber,非常感谢他们;最重要的是,要感谢我的妻子Mary以及儿子Max、Eli和Sam。
还要感谢那些指出本书以前版本的内容和排版错误以及提出改进意见的读者们,他们是Dave Barton、Patrick Benson、Ian Burton、Lawrence Chang、Jim DeVries、Ryan Esposto、Kim Farr、Sam Fitzpatrick、Bruce Franz、Owen Gailar、Rich Getz、Bob Griesemer、Jenny Guriel、Brenda Henry-Sewell、Ben Hensley、Jon Hereng、Drew Huber、John R Jackson、Bleu Jaegel、Natalie Kehr、Mark Lehner、Stephen Loscialpo、Brad Kaenel、Chris McGuire、Paul Niedenzu、E.J. O’Brien、Chip Pursell、Pranay Rajgarhia、Peter Riedlberger、Darrell Roberts、Luke Shulenburger、Mike Tomsic、John Walker、Joseph Walsh、Mark Weiss、P.C. Whidden、Chen Yan、Kyu Hwang Yeon和 J-F. Zurcher。
有些革命出其不意地吸引了全世界的眼球。Twitter、Linux操作系统和电视节目《典当之星》的异军突起颠覆了传统思维模式。
而Java语言的巨大成功却在人们的意料之中。自从Java语言于20年前面世以来,人们就对它充满殷切的期望。当Java融入到Web浏览器时,公众以无比的热情欢迎这种新语言的到来。
Sun公司联合创始人Bill Joy在介绍这种新语言时,毫不掩饰其孤注一掷的心态:“15年来,我们一直力图开发出一种更佳的编程语言和环境,用于创建更简单、更可靠的软件,Java就是这种努力的最终结晶。”
Sun于1991年开发出了Java,并于4年后向公众发布;2010年,Sun被Oracle收购。从Java面世起,Oracle就一直大力支持,它将继续支持这种语言,并提供新版本。
在过去的多年中,Java始终没有辜负媒体的大肆宣传。Java之于软件开发犹如咖啡之于饮料。咖啡伴随程序员们度过了无数个不眠之夜,而Java语言让程序员们完成软件开发后便可高枕无忧。
最初,Java是使用在Web浏览器中运行的程序来提升网站吸引力的技术;今天,一些大型网站仍使用它来驱动关系型数据库支持的动态Web应用程序;Java还被用于编写深受欢迎的Android手机和平板电脑应用,如《部落战争》和《Instagram》。
每个新Java版本都增强了其作为通用编程语言的功能,拓展了其应用领域。当前,Java的应用领域涉及桌面应用程序、Internet服务器、移动设备以及众多其他的环境。它还凭借使用Java开发的复杂应用程序在浏览器领域再造辉煌。
现在,Java语言的第9个主要版本—Java 8—完全能够同诸如C++、Python和Ruby等通用开发语言媲美。
您可能熟悉诸如Eclipse、NetBeans和IntelliJ IDEA等Java编程工具。它们可用于开发Java程序,同时您也可以使用Oracle提供的Java开发包。Java开发包是一组用于编写、编译和测试Java程序的命令行工具,可从网上免费下载。Oracle提供的另一个免费工具是NetBeans,这是一个用于创建Java程序的集成开发环境,可从www.netbeans.org下载。
本书全面介绍了如何使用Java最新版和Java标准版中最佳的技术来开发Java软件,Java标准版是使用最广泛的Java版本。本书中的程序都是使用NetBeans创建的,并经过了详细测试,让您能够快速展示每天学到的技能。
阅读本书后,您将知道Java语言为何能成为地球上使用最广泛的编程语言。
本书介绍Java语言以及如何使用它创建可运行在任何计算环境中的应用程序以及运行在手机和其他移动设备中的Android应用。阅读本书后,读者将对Java语言和Java类库有深入的了解,并能够开发用于完成诸如Web服务、数据库连接、XML处理和移动编程等任务的程序。
您将通过实践来学习,在每章中,您都将创建多个程序,这些程序演示了所介绍的主题。本书所有的程序源代码都可在配套网站www.java21days.com下载。该网站还提供了补充材料,如对读者问题的回答。
本书包括3周课程,分21章对Java语言及其类库进行了介绍。每周课程都阐述了开发Java程序的一个重要方面。
本书针对下列3类读者介绍Java语言:
阅读本书后,读者将熟悉Java语言的各个方面,并得心应手地使用Java来完成宏大的编程项目—无论是Web领域还是其他领域。
如果读者没有编程方面的经验,以前没有编写过程序,可能怀疑本书是否适合您。本书通过程序来阐述所有的概念,因此不管读者的经验是否丰富,都能够理解其中介绍的主题。如果读者熟悉变量和循环,也将从本书受益。本书的读者分以下几类:
如果读者不了解面向对象编程——Java采用的编程模式,也不用担心。本书假设读者没有面向对象设计方面的背景,在您学习Java的同时,将了解这种开发方法。
如果读者对编程一无所知,阅读本书时可能会有些吃力。Java很容易上手,读者只要耐心地阅读,并完成所有的示例,就能够掌握Java并开始使用它来编写自己的程序。
![]()
提供与当前讨论相关的信息,有时涉及技巧方面。
![]()
提供建议,如更简单的任务完成方式。
![]()
指出潜在的问题,帮助读者远离灾难。
每章最后是与该章主题相关的最常见的问题和作者的回答;还有小测验和练习,帮助读者测试对该章内容的掌握程度;另外,还有认证练习,可帮助读者备考Java认证。练习和认证练习的解决方案可在配套网站www.java21days.com找到。
Java试图解决众多领域的问题,实际上也确实在这方面取得了极大的成功。它让程序员能够开发应用程序服务器和手机程序、进行科学编程、编写软件以及进行星际导航等。
——Java语言之父James Gosling如是说
1995年首次发布时,Java编程语言是一个用于万维网的颇具创意的玩具,但有很大的发展潜力。
“潜力”是一个有时限的恭维之词。潜力迟早需要变成现实,否则将被“衰弱”、“浪费”、“失望”等取代。
通过阅读本书,读者在提高自身技能的同时,将能够对Java语言是否像它多年来被宣传的那样做出客观判断。
读者还将成为极具潜力的Java程序员。
现在的Java是第9个主要版本,它没有辜负当时人们对它的期望。在诸如NASA、IBM、Kaiser Permanente和Google等企业和组织中,有超过400万程序员学习了该语言并正在使用它。遍布世界各地的众多大学的计算机科学系将其列为标准教学课程。Java最初用于在网页中创建简单程序,而现在已被用于众多领域,其中包括:
对Web开发人员来说,Java仍很有帮助,但其应用领域已远远超出Web,成为最流行的通用编程语言之一。
现在,有关Java语言的故事已是家喻户晓。20世纪90年代中期,Sun公司的James Gosling和一个开发人员团队致力于开发一个交互式TV项目,Gosling对正在使用的C++感到失望。C++是一种面向对象编程语言,于20世纪80年代(比Java早了10年)在C语言的基础上开发。
Gosling把自己关在办公室,创建了一种适合其项目的语言,该语言解决了C++中一些令其失望的问题。
这个交互式TV项目以失败告终,但出乎人们意料的是,在此期间开发出来的新语言却适用于此时逐渐流行的一种新媒体——万维网。
Java于1995年首次与公众见面。虽然与C++(以及当今的Java)相比,该语言的大多数特性太初级,但被称作小程序(applet)的Java程序可作为网页的一部分运行在当时最流行的浏览器Netscape Navigator中。
这种功能——第一种用于Web的交互式编程技术——给这种新语言提供了极大的舆论攻势,在短短的6个月内便吸引了数十万开发人员。
在人们对Java Web编程技术的好奇过后,该语言的整体优势逐渐明朗,程序员们仍在继续使用它。有些调查表明,当前Java程序员人数超过了C++程序员。
自面世以来,Java语言的发展始终受Sun公司控制,但到2010年,情况发生了变化。2010年,Sun公司被数据库和企业软件巨头Oracle以74亿美元的价格收购。长期以来,Oracle一直在其产品中使用Java,存在支持Java的强烈愿望,并不断在新版本中改善其功能。
Java是一种面向对象的、独立于平台的安全语言,它比C++更容易学习,且比C和C++更能避免被误用。
面向对象编程(OOP)是一种软件开发方法,将程序视为一组协同工作的对象。对象是使用被称作类的模板创建的,它们由数据和使用数据所需的语句组成。Java是完全面向对象的,在本章后面,当您创建第一个类并使用它来创建对象时将明白这一点。
独立于平台指的是程序无须修改便能运行在不同的计算环境中。Java程序被编译成一种名为字节码的格式,而字节码可被任何带Java虚拟机(JVM)的计算机或设备运行。您可以在Windows 10机器上创建Java程序,然后在Linux Web服务器、使用OS 10.10的Apple Mac和三星Android手机上运行。只要平台安装了JVM,就能运行字节码。
虽然比其他语言更容易学习是程序员们争论的焦点之一,但Java主要在以下方面比C++更容易。
Java之所以安全的两个关键因素是没有指针且能自动管理内存。
介绍Java后,接下来应用其中的一些概念,创建您的第一个Java程序。
在读者从头到尾阅读本书后,将对Java的功能有深入了解,包括图形、文件输入和输出、XML处理和Android应用程序开发。您将能编写运行在网页、个人计算机和Web服务器以及其他计算环境中的Java程序。
开始编写程序之前,您必须在计算机上安装用于编辑、编译和运行Java程序(这些程序使用的是最新的Java 8版本)的软件。
有多种流行的集成开发环境(IDE)支持Java 8,如IntelliJ IDEA和开源软件Eclipse。
如果您在学习Java语言的同时学习使用这些工具,将是一项非常艰巨的任务。大多数IDE主要针对的是需要提高效率的、经验丰富的程序员,而不是刚开始学习一门新语言的新手。
最简单的Java开发工具是Java开发包,可从www.oracle.com/technetwork/java/javase/downloads免费下载。
每当Oracle发布新的Java版本时,都会在网上提供一个支持该版本的免费开发包。最新的版本为Java SE Development Kit 8。
出于简化的目的,本书通常将该语言及其开发包简称为Java和JDK。
使用JDK开发Java程序的缺点在于,这是一组命令行工具,因此没有用于编辑程序、将其转换为Java类并进行测试的图形用户界面。命令行是用于输入文本命令的提示符,在Windows中为程序“命令提示符”。
Oracle向Java程序员提供了优秀的免费IDE——NetBeans,可从网站www.netbeans.org下载。对大多数人来说,NetBeans都比JDK更易于使用,因此本书将使用NetBeans。
如果您的计算机没有安装任何Java开发工具,而您又想尝试一下NetBeans,可参阅附录A,它简要地介绍了如何使用该软件,包括如何下载并安装NetBeans,以及如何使用它来创建一个Java程序,以确保该程序能正确运行。
在计算机上安装支持Java 8的Java开发工具后,便可以开始学习使用该语言了。如果您的计算机没有安装这样的工具,现在该安装了——最好是NetBeans。
有关其他Java IDE的更详细信息,请参阅IDEA和Eclipse网站,网址分别是www.jetbrains.com/idea和www.eclipse.org。在本书的第21章,将使用IDE Android Studio(一种IntelliJ IDEA)来创建移动应用。
对新的Java程序员来说,最大的挑战在于学习该语言的同时学习面向对象编程。
如果您不熟悉这种编程方式,这听起来可能有些令人沮丧,虽然如此,但您可以把它当作是一种买一赠一的回馈。您将通过学习Java来掌握面向对象编程技术,否则,您将无法使用这种语言。
面向对象编程是一种创建计算机程序的方法,它模仿了现实世界中物体被组合在一起的方式。
使用这种开发风格,可以创建出更可靠、更容易理解、可重用性更高的程序。
为此,必须首先研究Java是如何实现面向对象编程原理的。
如果您熟悉面向对象编程,本章的很多内容将起到温故知新的作用。即使跳过那些介绍性内容,也应创建示例程序,以积累一些开发、编译和运行Java程序的经验。
概念化计算机程序的方式很多,其中之一是将程序视为一系列依次执行的指令,这通常被称为过程化编程。很多程序员开始学习的都是过程化语言,如BASIC。
过程化语言模仿了计算机执行指令的方式,因此程序与计算机执行任务的方式一致。过程化程序员首先必须学习如何将问题分解为一系列简单的步骤。
面向对象语言从另一个角度来看待计算机程序,它将重点放在您要求计算机完成的任务,而不是计算机完成任务的方式上。
在面向对象编程中,计算机程序被视为一组相互协同、共同完成任务的对象。每个对象都是程序的独立部分,它以特定的、高度可控制的方式与其他部分进行交互。
在现实生活中,一个面向对象设计的例子是立体声音响系统。大多数系统都是通过将一组不同的对象组合在一起而构建起来的,这些对象通常称为组件。立体音响购物之旅结束时,您可能带着如下对象回家。
这些组件能够通过标准的输入/输出端子进行彼此交互。即使您买的音箱、低音喇叭、调谐器、唱机和CD播放器不是同一个厂家的,只要它们有标准端子,就可以将它们组合成一个立体声音响系统。
面向对象编程的工作原理与此相同:您创建新对象,并将其与Oracle或其他软件开发商提供的对象连接起来,以组合成程序。其中每个对象都是程序中的一个组件,它们以标准方式组合在一起,每个对象都在程序中扮演着特定角色。
对象是计算机程序中的独立元素,包含一组相关的特性,能完成特定的任务。
面向对象编程是基于现实世界的情况进行建模的,对象由多种更小的对象构成。
然而,组合对象只是面向对象编程的一个方面,另一个重要特征是使用类。
类是用于创建对象的模板。使用同一个类创建的每个对象都具有相似的特性。
类包含一组特定对象的所有特性。使用面向对象语言编写程序时,并不定义各个对象,而是定义用于创建这些对象的类。
使用Java编写网络程序时,您可能创建HighSpeedModem
类,它描述了所有计算机调制解调器的特征。这些设备都具备如下特征:
HighSpeedModem
类是调制解调器的抽象概念模型。要在程序中有能够实际操纵的具体东西,必须有对象:必须使用HighSpeedModem
类创建HighSpeedModem
对象。使用类创建对象的过程叫做实例化(instantiation),这就是对象也被称作实例的原因所在。
在程序中,可使用HighSpeedModem
类创建很多不同的HighSpeedModem
对象,其中每个对象都可以有不同的特征,如:
虽然有这么多的不同,两个HighSpeedModem
对象仍有足够多的共性,使其被视为相关的对象。
再来看一个例子:使用Java可以创建一个类来表示所有的命令按钮——可单击的矩形框,出现在窗口、对话框和程序图形用户界面的其他部分。
开发CommandButton
类时,可以定义如下特征:
CommandButton
类还可定义按钮被单击时的行为。
定义CommandButton
类后,就可以创建按钮实例了,即CommandButton
对象。这些对象都具有类定义的按钮的基本特征,但根据需要,每个对象都可以有不同的外观和行为。
通过创建CommandButton
类,可避免为程序中要使用的每个命令按钮重写这些代码。此外,如果需要的话,还可以重用该CommandButton
类来创建不同类型的按钮,无论是在当前程序中还是在其他程序中。
编写Java程序时,您实际上设计和构建了一组类。程序运行时,将根据需要使用这些类来创建对象,并使用它们。作为Java程序员,您的任务是创建一组合适的类,以完成程序要完成的任务。
好在不必每次从头开始。Java语言包含Java类库,其中的类超过4000个,实现了您所需的大部分基本功能。这些类随诸如JDK等开发工具一起被安装。
当您谈论如何使用Java语言时,实际谈论的是如何使用该类库以及Java定义的标准关键字和运算符。
类库处理很多任务,如数学函数、文本处理、图形、用户交互以及网络功能等。使用这些类与使用您自己创建的Java类没有什么不同。
对于复杂的Java程序,可能需要创建一整套新类,这些类可组成独立的类库,以便在其他程序中使用。
重用是面向对象编程的基本优点之一。
在Java类库中,一个标准Java类是
javax.swing
包中的JButton
,它提供了上述虚构CommandButton
类的所有功能,还有众多其他的功能。在第9章,您将使用这个类来创建对象。
Java类包含两种不同的信息:属性和行为。
这两者在MarsRobot
中都有,这是今天将作为类实现的项目。该项目使用计算机模拟行星探测工具,灵感来自NASA喷气推进实验室(Jet Propulsion Laboratory)用来探测火星表面地质情况的火星探测车(Mars Exploration Rovers)。
创建该程序之前,您需要学习一些如何使用Java编写面向对象程序的知识。刚接触时,面向对象概念可能难以理解,但本书将给您提供大量将这些概念付诸实践的机会。
属性(attribute)是对象区别于其他对象的数据,可用于确定属于该类的对象的外观、状态和其他性质。
探测工具可能有如下属性。
在类中,属性是通过变量定义的,变量是计算机程序中用来存放信息的位置。实例变量是这样的属性,即它们的值随对象而异。
实例变量(instance variable)定义了特定对象的属性。对象的类定义了属性的类型,每个实例都存储了自己的属性值。实例变量也被称为对象变量(object variable)或成员变量(member variable)。
每个类属性都有一个相应的变量,可以通过修改该变量的值来修改对象的属性。
例如,MarsRobot
类定义了一个名为speed
的实例变量。这必须定义成一个实例变量,因为每个机器人都以不同的速度运动。可以通过修改机器人的speed
实例变量,使该机器人更快或更慢地移动。
创建对象时,可以给实例变量赋值,并在对象的整个生命期中保持不变;也可以在程序运行过程中使用该对象时,给它指定不同的值。
对于其他变量,让类的全部对象共享同一个值更合理,这些属性叫做类变量。
类变量(class variable)定义了类的属性。该变量用于类本身及其所有实例,因此不管使用该类创建了多少个对象,都只存储该变量的一个值。
在MarsRobot
类中,存储机器人最大移动速度的变量topSpeed
就是一个类变量。如果使用实例变量来存储这种速度,则在每个对象中,该变量的值都可能不同。这可能引发问题,因为没有机器人能超过指定的速度。
使用类变量可以避免这种问题,因为类的所有对象共享相同的值。每个MarsRobot
对象都能够访问该变量。
行为(behavior)指的是对象能够对自身和其他对象执行的操作。行为可以用来修改对象的属性、接收来自其他对象的信息以及向其他对象发送消息让它们执行任务。
火星机器人可能有如下行为:
行为是使用方法实现的。
方法(method)是类中一组用来完成特定任务的相关语句。它们用来针对对象本身或其他对象执行特定任务,相当于其他编程语言中的函数和子程序。设计良好的方法只执行一项任务。
对象间能够通过方法彼此通信。类或对象可能调用其他类和对象的方法,其原因很多,例如:
例如,两个火星机器人可以使用方法来报告彼此的位置,以免碰撞;一个机器人可以要求另一个停下来,以便它能够顺利通过。
正如变量分为实例变量和类变量一样,方法也分为实例方法和类方法。实例方法(instance method)很常见,因此它们通常被简称为方法,用于处理类的一个对象。如果一个方法对各个对象进行修改,它必须是实例方法。类方法(class method)适用于类本身。
为说明类、对象、属性和行为,您将开发一个MarsRobot
类,使用这个类创建对象并在程序中使用它们。
该程序的主旨是探索面向对象编程。有关Java编程语法的更详细的信息,请参阅第2章。
本书创建Java程序时,使用的开发工具主要是NetBeans。NetBeans将Java类组织成项目。使用项目来存储您在本书创建的类很有帮助。如果您还没有创建项目,现在就这样做。
1.选择菜单“文件”>“新建项目”,这将打开“新建项目”对话框。
2.在“类别”窗格中选择Java。
3.在“项目”窗格中选择“Java应用程序”,再单击“下一步”按钮,这将打开“新建Java应用程序”对话框。
4.在文本框“项目名称”中输入项目名(我使用的是Java21
)。在您输入项目名称的同时,文本框“项目文件夹”的内容将相应地更新。请将这个文件夹记录下来——您编写的Java程序将存储在这个文件夹中。
5.取消选择复选框“创建主类”。
6.单击“完成”按钮。
这将创建一个项目,您可在本书中始终使用它。
如果您以前创建过项目,可能已经在NetBeans中打开了它(如果没有,请选择菜单“文件”>“打开最近的项目”,并选择该项目)。您新建类时,它将添加到当前打开的项目中。
新建的项目将在NetBeans中打开。下面在这个项目中添加一个新类。
1.选择菜单“文件”>“新建文件”,打开“新建文件”对话框。
2.在“类别”窗格中选择Java。
3.在“文件类型”窗格中选择“空Java文件”,再单击“下一步”按钮,这将打开“空Java文件”对话框。
4.在文本框“类名”中输入MarsRobot
,文本框“创建的文件”中显示了您将创建的文件的名称——MarsRobot.java
,且不能编辑。
5.单击“完成”按钮。
这将打开NetBeans源代码编辑器,其中包含一个空文件。输入程序清单1.1所示的代码,再选择菜单“文件”>“保存”,这将保存文件MarsRobot.java
。
不要输入该程序清单中每行开头的行号,它们不是程序的组成部分。本书使用行号旨在方便描述各个代码行。
程序清单1.1 MarsRobot.java的完整源代码
1: class MarsRobot {
2: String status;
3: int speed;
4: float temperature;
5:
6: void checkTemperature() {
7: if (temperature < -80) {
8: status = "returning home";
9: speed = 5;
10: }
11: }
12:
13: void showAttributes() {
14: System.out.println("Status: " + status);
15: System.out.println("Speed: " + speed);
16: System.out.println("Temperature: " + temperature);
17: }
18: }
当您保存该文件时,如果没有错误,NetBeans将自动创建MarsRobot
类。这个过程称为编译类,使用的是名为编译器的工具。编译器将源代码行转换为Java虚拟机能够运行的字节码。
在程序清单1.1中,第1行的class
语句定义了一个名为MarsRobot
的类。从第1行的大括号({)
到第18行的大括号(}
)之间的所有内容都属于这个类。
MarsRobot
类包含3个实例变量和2个实例方法。
实例变量是在第2~4行定义的:
String status;
int speed;
float temperature;
变量名为status
、speed
、temperature
,其中每个变量都将用来存储一种不同类型的信息。
status
:存储一个String
对象——一组字母、数字、标点和其他字符。
speed
:存储一个int
对象,即整数值。
temperature
:存储一个float
对象,即浮点数值。
String
对象是使用Java类库中的String
类创建的。
从该程序可知,类可以将对象作为实例变量。
MarsRobot
类的第一个实例方法是在第6~11行定义的:
void checkTemperature() {
if (temperature < -80) {
status = "returning home";
speed = 5;
}
}
方法的定义方式与类相似,首先是指定方法名称、返回值和其他内容的语句。
CheckTemperature( )
方法位于第6行和第11行的大括号之间。可对MarsRobot
对象调用该方法,以确定其温度。
该方法检查对象的temperature
实例变量的值是否小于-80。如果是,则修改另外两个实例变量:
status
改为returning home,这表明温度太低,机器人应返回基地;第二个实例方法——showAttributes( )
是在第13~17行定义的:
void showAttributes() {
System.out.println("Status: " + status);
System.out.println("Speed: " + speed);
System.out.println("Temperature: " + temperature);
}
这个方法使用System.out.println( )
来显示3个实例变量的值,同时显示一些文本用于解释每个值的含义。
如果还没有保存该文件,请选择菜单“文件”>“保存”。如果保存文件后没有修改过它,该菜单项将不可用。
即便您正确地输入了程序清单1.1所示的代码,并将其编译成了类,也无法使用它来做任何事情。您所创建的类定义了MarsRobot
对象,但没有创建这种对象。
使用MarsRobot
类的方式有两种:
MarsRobot
类中添加一个特殊的类方法——main( )
,使之能作为一个应用程序运行;然后在方法main( )
中创建MarsRobot
对象。这里使用第一种方法。
程序清单1.2是Java类MarsApplication
的源代码,它创建一个MarsRobot
对象、设置其实例变量并调用其方法。请按前面介绍的步骤在NetBeans中新建一个文件,并将其命名为MarsApplication
;具体步骤如下。
1.选择菜单“文件”>“新建文件”,打开“新建文件”对话框。
2.在“类别”窗格中选择Java。
3.在“文件类型”窗格中选择“空Java文件”,再单击“下一步”按钮,这将打开“空Java文件”对话框。
4.在文本框“类名”中输入MarsApplication
,文本框“创建的文件”中显示了您将创建的文件的名称——MarsApplication.java
。
5.单击“完成”按钮。
在NetBeans源代码编辑器中,输入程序清单1.2所示的代码。
程序清单1.2 Mars` Application.java`的完整源代码
1: class MarsApplication {
2: public static void main(String[] arguments) {
3: MarsRobot spirit = new MarsRobot();
4: spirit.status = "exploring";
5: spirit.speed = 2;
6: spirit.temperature = -60;
7:
8: spirit.showAttributes();
9: System.out.println("Increasing speed to 3.");
10: spirit.speed = 3;
11: spirit.showAttributes();
12: System.out.println("Changing temperature to -90.");
13: spirit.temperature = -90;
14: spirit.showAttributes();
15: System.out.println("Checking the temperature.");
16: spirit.checkTemperature();
17: spirit.showAttributes();
18: }
19: }
选择菜单“文件”>“保存”,NetBeans
将自动把这个文件编译成MarsApplication
类,其中包含可供JVM运行的字节码。
在编译或运行程序时如果遇到了问题,可在本书的配套站点www.java21days.com下载源代码和其他相关文件。
编译该应用程序后,可运行它。为此,可选择菜单“运行”>“运行文件”。在NetBeans的“输出”窗口中,将显示MarsApplication
类的输出,如图1.1所示。
图1.1 MarsApplication
类的输出
根据程序清单1.2可知,类方法main( )
执行了以下操作。
main( )
方法。所有main( )
方法的格式都与此相同,这将在第5章介绍。现在,您需要注意的是关键字static
,它表明该方法是一个类方法,供所有MarsRobot
对象共享。MarsRobot
对象。该对象被命名为spirit
。status
被设置为exploring,speed
为2,temperature
为-60。dante
对象的showAttributes( )
方法。这个方法显示实例变量status
、speed
和temperature
的当前值。System.out.println( )
语句在输出设备(您的显示器)中显示圆括号内的文本。speed
实例变量的值设置为3。temperature
实例变量的值设置为-90。spirit
对象的checkTemperature( )
方法。该方法检查实例变量temperature
的值是否小于-80。如果是,则将新的值赋予status
和speed
。
如果由于某种原因,您不能使用NetBeans来编写Java程序,而必须使用JDK,请参阅附录D和E。附录D介绍了如何安装JDK,而附录E介绍了如何使用JDK来编译和运行Java程序。
Java面向对象编程还涉及另外三个概念:继承、接口和包,这些都是用于组织类和类行为的机制。
继承是面向对象编程中最重要的概念之一,直接影响您如何设计和编写Java类。
继承是一种机制,让一个类能够继承另一个类的行为和属性。
通过继承,一个类可自动拥有现有类的功能,因此只需定义与现有类不同的地方。
通过继承,所有的类(无论是您创建的类,还是Java类库中的类)都以严格的层次结构来组织。
继承其他类的类叫子类,被继承的类叫超类。
一个类只能有一个超类,但可以有任意数目的子类。子类继承了其超类的所有属性和行为。
实际上,这意味着如果超类具备您的类所需的行为和属性,则无须重新定义或复制代码,便可获得同样的行为和属性。子类将自动从其超类那儿获得这些东西,而超类又从其超类获得相应的东西,依此类推。这样便形成了层次结构。子类将拥有层次结构中位于它上面所有类的特性,同时也有自己的特性。
这与您从父母那里继承各种东西(如身高、头发颜色、喜欢花生黄油和香蕉三明治)相同。它们也从其父母那里继承了一些特征,它们的父母又是从它们父母的父母那里继承,这样一直追溯到伊甸园、宇宙大爆炸之前。
图1.2显示了类的层次排列方式。
图1.2 类层次结构
Java类层次结构的顶端是类Object
。
所有的类都是从这个超类继承而来的。Object
是层次结构中最通用的类,定义了Java类库中的所有类的行为。
在层次结构中越往下,类的用途越具体。在层次结构的顶部定义的是抽象概念,越往下,这些概念越具体。
使用Java创建新类时,常常希望它具备某个现有类的所有功能,并做一些修改。例如,您可能希望有一个新版本的CommandButton
,能够在单击时发出声音。
要不经过任何重建工作而得到CommandButton
的所有功能,可以将您的类定义为CommandButton
的子类。
这样,您的类将自动继承CommandButton
定义的行为和属性以及CommandButton
的超类定义的行为和属性。您所需要关心的只是新类不同于CommandButton
的内容。子类化(subclassing)机制用于定义新类及其与超类之间的差别。
子类化指的是通过继承已有的类来创建一个新类。子类只需指出其属性和行为不同于超类的地方。
如果您的类定义了全新的行为,且不是其他类的子类,则可以直接继承Object
类。
如果您创建类时没有指定超类,Java将认为它直接继承Object
。前面创建的MarsRobot
类没有指定超类,因此是Object
的子类。
如果您创建了大量的类,则应该让您的类从现有类层次结构继承,并构建自身的层次结构。这有如下优点:
例如,假设创建了一个Java类来实现勘测机器人的所有特征(这并不需要太多的想象力)。
这个MarsRobot
类已经完成,它工作正常,一切都很好。现在您在NASA的老板要求您创建一个名为MercuryRobot
的Java类。
这两种机器人有相似的特征:都是在恶劣环境下执行研究工作的机器人,且都跟踪其当前的温度和速度。
您首先想到的可能是,打开源代码文件MarsRobot.java
,将其大部分代码复制到新的源代码文件MercuryRobot.java
,再根据新机器人的用途做必要的修改。
更好的办法是找出MarsRobot
和MercuryRobot
的共同功能,并将它们放到一个更通用的类层次结构中。对于只有类MarsRobot
和MercuryRobot
的情况,这也许是项繁重的工作,但如果您还想加入MoonRobot
、UnderseaRobot
和DesertRobot
,情况将如何呢?将共同的行为放在一个或多个可重用的超类中将极大地减少所需的工作量。
要设计一个满足该目标的类层次,应从Object
开始,它是所有Java类的祖宗。
这些机器人的老祖宗可能名为Robot
。一般而言,机器人可被视为一种自控的探测设备。在Robot
类中,您只定义使其成为自控的、用于探测的设备的行为。
在Robot
下面有两个类:WalkingRobot
和DrivingRobot
。这两个类之间明显的区别在于,一个靠腿移动,另一个靠轮子移动。步行机器人的行为可能包括弯腰捡东西、蹲下、跑动等。驱动式机器人的行为与此不同。图1.3显示了您目前已有的类层次结构。
现在,这个层次可以更具体。从WalkingRobot
类可以派生出多个类:ScienceRobot
、GuardRobot
、SearchRobot
等。另外,您可以抽取出更多的功能,创建两个中间类TwoLegged
和FourLegged
,其中每个类都有不同的行为(见图1.4)。
图1.3 基本的Robot层次结构图
图1.4 2条腿和4条腿的步行机器人
最后,整个层次结构便完成了,并为MarsRobot
找到了合适的位置。它可以是ScienceRobot
的子类,ScienceRobot
是WalkingRobot
的子类,WalkingRobot
是Robot
的子类,而Robot
又是Object
的子类。
诸如状态、温度和速度等属性应放在什么位置呢?应放在最合适的地方。因为所有机器人都需要跟踪其所处环境的温度,因此在Robot
中将temperature
定义为一个实例变量是合理的。这样所有的子类都将有这个实例变量。请记住,只需在层次结构定义行为或属性一次,它将自动被每个子类继承。
要设计出高效的类层次结构,需要做大量的规划和修订。当您试图将新的属性和行为加入到层次结构中时,很可能发现需要将一些类移到另一个位置,以便减少重复的特征和冗余的代码。
在Java中,继承比现实生活中的继承要简单得多。Java中继承时,不需要遗嘱,也不需要法庭。
当您创建新对象时,Java将记录该对象及其超类的每个变量。这样,所有的类组合成当前对象的模板,每个对象都将包含合适的信息。
方法的工作原理与此相似,新对象可以访问其所属类及其超类的所有方法,这是在运行期间当方法被使用时动态确定的。如果您调用了特定对象的某个方法,Java虚拟机将首先检查该对象所属的类是否有该方法。如果没有,则在其超类中查找,依此类推,直到找到该方法的定义为止,如图1.5所示。
图1.5 如何在类层次结构中查找方法
如果子类中定义了名称和其他方面都与超类相同的方法,情况将复杂起来。在这种情况下,首先被找到的方法是被使用的方法(从层次结构的底部开始向上查找)。
因此,可以在子类中创建一个方法来防止调用超类中定义的方法。为此,该方法的名称、返回值和参数必须与超类方法相同。这被称为覆盖,如图1.6所示。
Java的继承形式称为单继承(single inheritance),因为每个Java类都只能有一个超类(虽然任何超类都可以有多个子类)。
在其他面向对象编程语言(如C++)中,类可以有多个超类,并继承所有超类的变量和方法,这叫多重继承(multiple inheritance)。Java只允许单继承,简化了继承机制。
图1.6 覆盖方法
单继承简化了类之间的关系,并使这些类实现的功能更容易理解和设计。然而,它也有局限性,尤其是当您有一些相似的行为,它们需要在类层次结构的不同分支间进行复制时。Java通过使用接口来解决这些共享行为的问题。
接口是一组方法,它指出类除了从超类继承的行为外,还有其他行为。接口中的方法并没有定义行为,这项任务将由实现该接口的类去完成。
例如,Comparable
接口包含一个这样的方法,即对属于同一个类的两个对象进行比较,以判断在排序链表中,哪个应在前面。任何实现了该接口的类都告诉其他对象,它能够确定其对象的排列顺序。如果没有该接口,类将不会有这种行为。
有关接口的内容将在第6章介绍。
在Java中,包用于将相关的类和接口编组,使得更容易在其他类中引用它们;包还避免了类之间潜在的命名冲突。
引用Java类时,可使用简短的名称,如Object
,也可使用完整的名称,如java.lang.Object
。
默认情况下,您的Java类只需通过简短的名称就可引用java.lang
包中的类。java.lang
包提供了基本的语言功能,如字符串处理和数学运算。要使用其他包中的类,必须使用完整的包名或使用import
语句将包导入到源代码文件中。
例如,由于类Color
位于包java.awt
中,所以在程序中通常要使用java.awt.Color
来引用它。
如果使用import
语句导入了java.awt
包,便可使用Color
来引用这个类。
要指定类所属的包,可使用package
语句。您在本书中创建的很多类都放在包com.java24hours中,它们使用了类似于下面的package
语句:
package com.java24hours;
这条语句必须位于类的最前面。如果没有这样的语句,就像本章创建的MarsRobot
和MarsApplication
那样,类将包含在被称为默认包的未命名包中。
如果您是首次接触面向对象编程,则本章的内容太理论化,您可能一时无法理解。
当您的头脑中满是OOP概念和术语时,可能担心无法消化余下的关于Java的20章内容。
不要烦恼。保持冷静,继续向前。
至此,您应对类、对象、属性和行为有了基本了解,同时还应熟悉了实例变量和方法。在下一章,您将使用它们。
有关面向对象编程的其他方面(如继承和包),将在后面的课程中进行更详细的介绍。
在本书后面的每个课程中,您都将使用面向对象编程。要使用Java编写程序,别无他途。
阅读完第1周的课程后,您将拥有使用对象、类、继承以及面向对象编程的其他所有方面的经验。
问:实际上,方法是在类中定义的函数。既然它们无论从外观和行为方面都类似于函数,为什么不将它们叫做函数呢?
答:有些面向对象编程语言确实将它们叫做函数(C++将它们叫做成员函数)。其他一些面向对象语言将位于类(对象)内、外的函数区分开来,因为在这些语言中,使用不同的术语对理解每个函数的工作原理至关重要。因为其他语言有这种区别,同时术语“方法”在面向对象技术中很常用,所以Java也使用这个术语。
问:实例变量和实例方法同类变量和类方法之间有何区别?
答:在Java程序中,您所做的几乎每项工作涉及的都是实例(也叫对象)而不是类。然而,对于有些行为和属性,存储在类本身中要比存储在对象中更合理。例如,java.lang
包中的Math
类包含一个名为PI
的变量,它存储的是π的近似值。这个值是不变的,因此这个类的不同对象没有必要保留自己的PI
变量。另一方面,每个String
对象都包含了一个length( )
方法,它计算该String
中的字符数。这个值对于String
类的每个对象都可能不同,因而它必须是实例方法。
类变量始终驻留在内存中,直到Java程序结束运行,因此应慎用类变量。如果类变量指向一个对象,该对象也将始终驻留在内存中。这是一种导致程序占据太多内存且运行缓慢的常见问题。
问:如果在Java类中导入整个包,是否会增大这个类编译后的尺寸?
答:不会。术语“导入”容易让人误解。关键字import
不会将指定类或包的字节码加入到当前创建的类中,而只是使得在一个类中引用另一个类更容易。
通过导入,在Java语句中引用类时,可使用简短的名称,这是导入的唯一目的。在代码中,如果总是必须指定完整的类名,如javax.swing.JButton
和java.awt.Graphics
,而不是JButton
和Graphics
,那将非常繁琐。
请回答下述3个问题,以复习本章介绍的内容。
1.类又叫什么?
A.对象
B.模板
C.实例
2.创建子类时,必须定义它的哪些方面?
A.什么都不用定义,它已定义好了
B.不同于超类的内容
C.各个方面
3.类的实例方法表示的是什么?
A.类的属性
B.类的行为
C.根据类创建的对象的行为
1.B。类是一个抽象模板,用于创建彼此相似的对象。
2.B。需要定义子类与超类有什么不同。由于继承,相同的内容已定义好。从技术上说,答案A是正确的,但如果子类的一切都与超类相同,就没有必要创建它。
3.C。实例方法指的是特定对象的行为,而类方法指的是属于该类的所有对象的行为。
下面的问题是Java认证考试中可能出现的问题,请回答该问题,而不要查看本章的内容。
下面的哪些说法是正确的?
A.使用同一个类创建的所有对象都必须相同
B.使用同一个类创建的对象可以有不同的属性
C.对象将继承用于创建它的类的属性和行为
D.类将继承其超类的属性和行为
答案见本书的配套网站www.java21days.com。单击链接01,再单击链接Certification Practice。
为巩固本章介绍的知识,请尝试完成下面的练习。
1.在Mars Application
类的main( )
方法中,再创建一个名为opportunity
的MarsRobot
对象,设置其实例变量并将它们的值显示出来。
2.为国际象棋中的棋子创建一个继承层次结构,并决定在层次结构的什么位置定义实例变量color
、startingPosition
、forwardMovement
和sideMovement
。
解决方案见本书的配套网站www.java21days.com。
Java程序是由类和对象组成的,而对象和类又是由方法和变量组成的。方法是由语句和表达式组成的,表达式又由运算符组成。
至此,您可能担心Java就像俄罗斯套娃,除最小的洋娃娃外,每个洋娃娃里边都有一个更小的洋娃娃,而后者同前者一样错综复杂。
本章将消除大洋娃娃的困扰,揭示Java编程的最小元素。本章暂时撇开类、对象和方法,介绍单行Java代码中的基本元素。
这包括以下内容:
您在Java程序中要完成的所有任务都可分解为一系列的语句。在编程语言中,语句是简单的命令,它导致计算机执行某种操作。
语句表示程序中发生的单个操作。下面是3条简单的Java语句:
int weight = 225;
System.out.println("Free the bound periodicals!");
song.duration = 230;
有些语句能够提供一个值,如在将两个数相加或比较两个变量是否相等时。
生成一个值的语句被称为表达式。这个值可以存储下来,供程序后面使用,也可以立即用于另一条语句中或被丢弃。语句生成的值称为返回值。
有些表达式生成数字值,如将两个数相加或相乘时;有些表达式生成布尔值(true或false)或Java对象,这将在本章后面介绍。
虽然在很多Java程序中,每条语句占一行,但这只是一种格式,并不能决定语句到哪里结束。Java语句都以分号(;)结尾。程序员可以在一行放置多条语句,且它们都能够通过编译,如下所示:
spirit.speed = 2; spirit.temperature = -60;
为了让您的程序对其他程序员(以及您自己)来说更容易理解,应遵循每条语句占据一行的约定。
在Java中,使用左大括号({)和右大括号(})将语句编组。位于这两个字符之间的语句称为块(block)或块语句(block statement),这将在第4章更详细地介绍。
在第1章创建的应用程序MarsRobot中,您使用变量来跟踪信息。变量是程序运行时能够存储信息的地方。可在程序的任何地方对其中的值进行修改——因此被称为变量。
要创建变量,必须提供名称并指定它存储的信息类型。还可以在创建变量的同时给它指定初始值。
在Java中,有3种变量:实例变量、类变量和局部变量。
正如第1章中指出的,实例变量用于定义对象的属性。
类变量定义类的属性,适用于类的所有实例。
局部变量用于方法定义乃至方法中更小的语句块中。仅当Java虚拟机执行这些方法或语句块时,它们才被使用,离开方法或块之后,它们将不复存在。
虽然这3种变量的创建方式极其相似,但在使用方式上,类变量和实例变量不同于局部变量。本章介绍局部变量,而实例变量和类变量将在第3章介绍。
在Java程序中使用变量之前必须先创建它——声明其名称和存储的信息类型。首先指出信息类型,然后是变量名,下面是一些变量声明的例子:
int loanLength;
String message;
boolean gameOver;
在上述示例中,int
类型表示整数,String
是用来存储文本的对象,boolean
用来存储true/false值。
就像其他Java语句一样,局部变量可在方法的任何地方声明,但必须在使用前声明。
下面的示例在程序的main()方法开头声明了3个变量:
public static void main(String[] arguments) {
int total;
String reportTitle;
boolean active;
}
创建多个类型相同的变量时,可在同一条语句中声明它们,并用逗号将各个变量分开。下面的语句声明了3个名为street
、city
和state
的String
变量:
String street, city, state;
声明变量时,可以使用等号给它赋值。下面的语句创建新变量并给它们指定初始值:
String zipCode = "02134";
int box = 350;
boolean pbs = true;
String name = "Zoom", city = "Boston", state = "MA";
正如最后一条语句表明的,可以使用逗号分隔的方式给多个类型相同的变量赋值。
对于局部变量,在程序中使用它之前,必须给它赋值,否则程序将无法通过编译。因此,良好的习惯是给所有局部变量指定初始值。
默认情况下,实例变量和类变量的初始值取决于其数据类型。
0
。"\0"
。false
。null
。在Java中,变量名必须是以字母、下划线(_)或美元符($
)打头。
变量名不能以数字打头。在第一个字符之后,变量名可包含任何字母、数字、下划线和美元符号的组合。
另外,Java语言使用Unicode字符集,该字符集包括标准字符集,外加几千个用于表示国际字母的字符。有Unicode字符号的重音字符和其他符号也可用于变量名中。
在程序中给变量命名并使用它时,别忘了Java是区分大小写的——字母的大小写必须一致。因此,同一个程序中可以有变量X
和x
,而rose
、Rose
和ROSE
是不同的变量。
在本书或其他地方的程序中,Java变量都被赋予一个有意义的名称,它们由多个单词组合而成。为方便辨识,可使用下述通用规则:
下面的变量声明遵循了上述命名规则:
Button loadFile;
int localAreaCode;
boolean quitGame;
虽然在变量名中可以使用下划线,但除非在如下情况下,否则不应使用它:整个变量名都是大写时,使用下划线将各个单词分开,如下所示:
static int DAYS_IN_WEEK = 7;
本章后面将介绍要将整个变量名都大写的原因。
虽然在变量名中可以使用美元符号,但在任何情况下都不应这样做。Java官方文档建议不要使用它,因此程序员都遵循这种约定。
除名称外,变量声明还必须包括存储的信息类型,这可以是:
int
或boolean
;关于如何声明和使用数组变量,将在第4章介绍。本章重点介绍其他变量类型。
Java提供了8种基本数据类型,用于存储整数、浮点数、字符和布尔值。它们通常被称为简单类型(primitive type),因为它们是Java内置的而不是对象,这使得它们更容易创建和使用。不管在什么操作系统和平台上,这些数据类型的长度和特征都相同,这与其他编程语言的某些数据类型不同。
用于存储整数的数据类型有4种,如表2.1所示。具体使用哪种类型取决于要存储的整数大小。
表2.1 整型
类型 |
长度(bit) |
取值范围 |
---|---|---|
byte |
8 |
−128~127 |
short |
16 |
−32768~32767 |
int |
32 |
−2147483648~2147483647 |
long |
64 |
−9223372036854775808~9223372036854775807 |
所有这些类型都是有符号的,这意味着它们既可以存储正数,也可以存储负数。给变量指定哪种类型取决于需要存储的值的范围。所有这些整型变量都不能正确存储超出其取值范围的值,所以在指定类型时一定要小心。
另一种数值是浮点数,其类型为float
或double
。浮点数是带小数的数字。float
类型的取值范围为1.4E-45
到2.4E+38
;double
类型的精度更高,其取值范围为4.9E-324
到1.7E+308
。鉴于double
的精度更高,因此它通常比float
更佳。
char
类型用于存储单个字符,如字母、数字、标点和其他符号。
最后一种基本类型是boolean
。正如前面介绍过的,其取值为true
或false
。
所有这些变量类型名都是小写的,在程序中必须这样使用它们。存在与这些数据类型名称相同,但大小写不同的类,如Boolean
和Double
。在Java程序中,创建和引用它们的方式不同,因此大多数情况下不能互换。下一章将介绍如何使用这些特殊的类。
如果算上void,Java中实际上有9种基本类型。void表示“空”(nothing),用于指出方法不返回任何值。
除基本数据类型外,变量的类型还可以是类,如下所示:
String lastName = "Hopper";
Color hair;
MarsRobot robbie;
当变量的类型为类时,它指的是这种类或其子类的一个对象。
在上述代码中,最后一条语句声明一个名为robbie
的变量,用于存储Mars Robot
对象。下一章将介绍如何将对象和变量关联起来。
声明变量后,可以用赋值运算符(=
,等号)给它赋值。下面是两个赋值语句的例子:
idCode = 8675309;
accountOverdrawn = false;
如果需要存储在程序运行时可以修改的信息,使用变量很有用。
对于在程序运行过程中一直不变的值,可以用一种特殊的变量——常量。常量是值保持不变的变量。这里的“变量”有些用词不当。
为对象的所有方法定义共享值时,常量很有用。在Java中,可以创建各种类型的常量:实例常量、类常量和局部常量。
要声明常量,可在变量声明前加上关键字final
,并指定初始值,如下所示:
final double PI = 3.141592;
final boolean DEBUG = false;
final int PENALTY = 25;
可使用常量来表示对象的不同状态,然后测试这些状态。假设有一个这样的程序,它直接从数字键盘读取方向输入——8表示向上,4表示向左,6表示向右,2表示向下等,则您可以将这些值定义为整型常量:
final int LEFT = 4;
final int RIGHT = 6;
final int UP = 8;
final int DOWN = 2;
常量让程序更容易理解。为了说明这一点,请看下面哪条语句更清楚地说明了其功能:
guide.direction = 4;
guide.direction = LEFT;
在上述语句中,常量名都为大写,如DEBUG和LEFT。Java程序员都这样做,以表明这是常量而不是变量;虽然Java并未要求常量名必须大写,但您最好遵循这种做法。
常量名由多个单词组成时,将整个常量名都大写将导致各个单词难以区分开来,如ESCAPECODE。在这种情况下,应使用下划线将各个单词分开,如下所示:
final int ESCAPE_CODE = 27;
本章要介绍的第一个项目是一个这样的Java应用程序:创建多个变量,给它们赋初始值,然后显示其中两个变量的值。请启动NetBeans,并按如下步骤新建一个Java程序(其中有个步骤与第1章不同)。
1.选择菜单“文件”>“新建文件”打开“新建文件”对话框。
2.在“类别”窗格中选择Java。
3.在“文件类型”窗格中选择“空Java文件”,再单击“下一步”按钮,这将打开“空Java文件”对话框。
4.在文本框“类名”中输入Variables
,这将把源代码文件命名为Variables.java
。
5.在文本框“包”中输入com.java21days
(这就是与前一章不同的步骤)。
6.单击“完成”按钮。
在这里,您指定了类名和包名。包用于将相关的Java程序放在一起,类似于文件系统中的文件夹。在源代码编辑器中,输入程序清单2.1所示的代码。
程序清单2.1 Variables.java的完整源代码
1: package com.java21days;
2:
3: public class Variables {
4:
5: public static void main(String[] arguments) {
6: final char UP = 'U';
7: byte initialLevel = 12;
8: short location = 13250;
9: int score = 3500100;
10: boolean newGame = true;
11:
12: System.out.println("Level: " + initialLevel);
13: System.out.println("Up: " + UP);
14: }
15: }
选择菜单“文件”>“保存”将该文件存盘。NetBeans将自动编译该应用程序——如果没有错误。选择菜单“运行”>“运行文件”以运行该程序,其输出如图2.1所示。
图2.1 创建变量并显示它们的值
类所属的包是使用package
语句指定的,这种语句必须位于类的最前面:
package com.java21days;
这个类使用了4个局部变量和1个常量,并在第12~13行使用System.out.println()
来生成输出。
System.out.println()
是一个用于将字符串和其他信息显示到标准输出设备(通常是显示器)上的方法。
这个方法接收一个参数:一个字符串。为了将多个变量或字面值作为println( )
的参数,使用运算符+将它们合并成一个字符串。
Java还提供了方法System.out.print()
,它不在字符串后回车。要在同一行显示多个字符串,可连续调用方法print()
,而不是println()
。
为提高程序的可读性,最有效的方式之一是使用注释。注释是程序中的文本,说明了代码的作用。Java编译器在生成Java源代码文件的字节码版本时忽略注释,因此使用注释不会带来任何危害。
在Java程序中,可以使用3种不同的注释。
单行注释以两个斜杠(//)打头。从这些斜杠到行尾的所有内容都是注释,Java编译器将忽略它们,如下面的语句所示:
int creditHours = 3; // set up credit hours for course
从这些斜杠到行尾的所有内容都被忽略,因此在编译器看来,上述代码行与下面的代码等效:
int creditHours = 3;
多行注释以/打头,以/结束。这两个分界符之间的所有内容(可以横跨多行)都被视为注释,如下所示:
/* This program occasionally deletes all files on
your hard drive and renders it unusable
forever when you click the Save button. */
Javadoc注释以/**
打头,*/
以结束。这些分界符之间的内容都被视为用于描述类及其方法的官方文档。
Javadoc注释可被诸如javadoc(JDK中的一个命令行工具)等实用程序读取。javadoc使用这种注释来创建一组网页,用于说明Java类的功能、指出Java类在继承层次结构中的位置、描述其每个方法。
Java类库中每个类的官方文档都是根据Javadoc注释生成的。要查看最新的Java文档,请访问at http://docs.oracle.com/javase/8/docs/api。
附录E介绍了如何使用工具javadoc。
除变量外,还可以在Java语句中使用字面量。字面量可以是任何直接表示一个值的数字、文本或其他信息。
下面的赋值语句使用了字面量:
int year = 2016;
其中的字面量2016表示整数值2016。数字、字符和字符串都是字面量。Java有一些特殊类型的字面量,它们表示各种数字、字符、字符串和布尔值。
Java有几种整型字面量。例如,数字4是一个int
类型的整型字面量,可将其赋给byte
或short
类型的变量,因为它足够小,在这些整数类型的取值范围内。位于int
取值范围之外的整型字面量将被视为long
类型。也可以在后面加上字母L(或l)来指出字面量的类型为long
。例如,下面的语句将4视为一个long
值,如下例所示:
pennyTotal = pennyTotal + 4L;
该语句给变量pennyTotal
的当前值加上long
型字面值4。
要表示负的数字字面量,可在前面加上负号(−),如−45。
浮点数字面量使用句点(.)表示小数点,这与您想的完全相同。下面的语句使用字面量来设置一个double
变量的值:
double gpa = 3.55;
所有的浮点数字面量都被视为double
类型,而不是float
类型。要将字面量的类型指定为float
,可加上字母F(或f),如下所示:
float piValue = 3.1415927F;
在浮点数字面量中,可以使用指数表示法,即使用字母e(或E),而指数可以是负数。下面的语句使用了指数表示法:
double x = 12e22;
double y = 19E-95;
对于很大的整型字面量,为提高其可读性,可在其中添加下划线。这种下划线的作用与表示千分位的逗号相同,旨在让数字更易读。请看下面两个例子,其中一个使用了下划线:
int jackpot = 3500000;
int jackpot = 3_500_000;
其中两个字面量的值都是3500000,但第2条语句更清晰。Java编译器忽略这样的下划线。
Java也支持使用二进制、八进制和十六进制表示的数字字面量。
二进制是以2为基数的计数系统,这意味着每位只能是0或1。对计算机来说,由0和1组成的值最简单,也是重要的计算部分。在二进制中,从0开始依次为0、1、10、11、100、101等。每位称为一个比特,8比特为一个字节。二进制字面量以0b打头,如0b101(十进制值5)、0b11111111(十进制值127)。
八进制是以8为基数的计数系统,这意味着每位只能是0和7之间的值。在八进制数中,第8个数是10。八进制字面量以0打头,因此010表示十进制值8,012表示十进制值9,而020表示十进制值16。
十六进制是以16为基数的计数系统,每位可能的取值为16个。字母A~F表示最后的6个数字,因此这16个数依次为0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F。十六进制字面量以0x打头,如0x12(十进制值18)或0xFF(十进制值255)。
对有些编程任务而言,八进制和十六进制比十进制更适合。如果您曾设置过网页的背景颜色,可能使用过表示绿色、蓝色和奶油硬糖色的十六进制数,它们分别是0x001100、0x000011和0xFFCC99。
布尔值true
和false
也是字面量。boolean
变量的取值只能是true
或false
。
下面的语句给一个boolean
变量赋值:
boolean chosen = true;
如果您使用过其他语言,如C语言,则可能认为1和true等价,而0和false等价。在Java中,情况并非如此,必须使用值true和false来表示布尔值。
注意字面量true
并不需要用引号括起。如果被引号括起,则Java编译器会将其视为字符串。
字符字面量是用单引号括起的单个字符,如'a'
、'#'
和'3'
。您也许熟悉ASCII字符集,它包括128个字符,其中有数字、字母、标点和其他对计算有帮助的符号。Java使用16位的Unicode标准,除ASCII字符外,还支持其他数以千计的字符。
有些字符字面量表示的是非打印字符或不能通过键盘输入的字符。表2.2列出了一些特殊编码,它们用于表示这些特殊字符以及Unicode字符集中的字符。
表2.2 字符的转义编码
转义符 |
含义 |
---|---|
\n |
换行 |
\t |
水平制表符 |
\b |
退格 |
\r |
回车 |
\f |
换页 |
\\ |
反斜杠 |
\' |
单引号 |
\" |
双引号 |
\d |
八进制 |
\xd |
十六进制 |
\ud |
Unicode字符 |
表2.2的八进制、十六进制和Unicode转义编码中,字母d表示一个数字或十六进制数字(a~f或A~F)。
可在Java程序中使用的最后一种字面量表示一个字符串。Java中的字符串是一种对象,而不是一种基本数据类型。同时,不像C语言那样,字符串被存储在数组中。
因为字符串对象是Java中的真正对象,所以存在用于合并和修改字符串以及判断两个字符串是否相同的方法。
字符串字面量是用双引号括起的一系列字符,如下所示:
String quitMsg = "Are you sure you want to quit?";
String password = "drowssap";
字符串中可以包含表2.2列出的转义字符,如下所示:
String example = "Socrates asked, \"Hemlock is poison?\"";
System.out.println("Sincerely,\nMillard Fillmore\n");
String title = "Sams Teach Yourself Node in the John\u2122";
在上述最后一行代码中,在支持Unicode的系统上,Unicode编码序列\u2122
将生成一个TM符号。
虽然Java支持对Unicode字符的传输,但要在程序运行时显示这些字符,计算机也必须支持Unicode。Unicode提供了一种对字符进行编码的方式,可用于支持该标准的系统。Java支持任何Unicode字符的显示,只要该字符能够被主机的某种字体表示出来。
有关Unicode的更详细的信息,请访问Unicode联盟网站www.unicode.org。
虽然在程序中使用字符串字面量的方式与其他字面量类似,但在后台对它们的处理是不一样的。
对于字符串字面量,Java将其存储为String
对象。您不必像使用其他对象那样,显式地创建一个新对象,因此使用起来与基本数据类型一样简单。从这种意义上说,字符串与众不同——基本数据类型都不会被存储为对象。本章后面将更详细地介绍字符串和String
类。
表达式是一条能够提供值的语句。最常见的是数学表达式,如下面的例子所示:
int x = 3;
int y = x;
int z = x * y;
这3条语句都是表达式——它们提供了可被赋给变量的值。第1条语句将字面量3赋给变量x
。第2条语句将变量x
的值赋给变量y
。在第3条语句中,乘法运算符*
用来将x
和y
相乘,结果存储在变量z
中。
表达式可以是变量、字面量和运算符的任何组合,也可以是方法调用,因为方法能够将一个值返回给调用它的类或对象。
您知道,表达式所提供的值称为返回值。在Java程序中,可将这个值赋给变量或以其他方式使用。
大多数Java中的表达式使用了运算符,如*。运算符是一些特殊符号,用于数学函数、赋值语句和逻辑比较。
在Java中,有5种用来完成基本算术运算的运算符,如表2.3所示。
表2.3 算术运算符
运算符 |
含义 |
例子 |
---|---|---|
+ |
加 |
3+4 |
− |
减 |
5−7 |
* |
乘 |
5*5 |
/ |
除 |
14/7 |
% |
求模 |
20%7 |
每个运算符都有两个操作数,一边一个。减法运算符也可以用来对单个操作数求反,即将操作数与−1相乘。
使用除法时,要注意操作数的类型。如果将除法运算的结果存储在整型变量中,结果将向下取整,因为int
类型不能处理浮点数。
例如,如果将结果存储在int
变量中,则表达式31/9
的结果为3。
使用运算符%
的求模运算得到的是除法运算的余数。例如,31%9
的结果是4,因为31被9除的余数是4。
很多针对整数的算术运算的结果为int
值,而不管操作数是什么类型。处理其他数值类型,如浮点数或长整型时,应确保操作数的类型与所需结果的类型相同。
要创建的下一个项目是个Java类,它演示了如何使用Java执行简单的算术运算。为此,在NetBeans中新建一个空Java文件,将其命名为Weather
并放在com.java21days
包中,再在源代码编辑器中输入程序清单2.2所示的代码。输入完毕后选择菜单“文件”>“保存”将这个文件存盘。
程序清单2.2 源代码文件Weather.java
1: package com.java21days;
2:
3: public class Weather {
4: public static void main(String[] arguments) {
5: float fah = 86;
6: System.out.println(fah + " degrees Fahrenheit is ...");
7: // To convert Fahrenheit into Celsius
8: // begin by subtracting 32
9: fah = fah - 32;
10: // Divide the answer by 9
11: fah = fah / 9;
12: // Multiply that answer by 5
13: fah = fah * 5;
14: System.out.println(fah + " degrees Celsius\n");
15:
16: float cel = 33;
17: System.out.println(cel + " degrees Celsius is ...");
18: // To convert Celsius into Fahrenheit
19: // begin by multiplying by 9
20: cel = cel * 9;
21: // Divide the answer by 5
22: cel = cel / 5;
23: // Add 32 to the answer
24: cel = cel + 32;
25: System.out.println(cel + " degrees Fahrenheit");
26: }
27: }
选择菜单“运行”>“运行文件”运行该程序,它将生成如图2.2所示的输出。
图2.2 使用表达式对温度进行转换
该Java应用程序的第5~14行使用算数运算符将华氏温度转换为摄氏温度。
fah
,并将其初始化为86。fah
的当前值。fah
的值减去32。fah
的值除以9。fah
的值乘以5。fah
的值转换为摄氏温度后,再次显示它。第16~25行与此类似,但执行相反的转换——将摄氏温度转换为华氏温度。
这些简化的赋值运算符与它们所代表的更长的赋值语句等效。然而,如果赋值语句的一边是复杂的表达式,将出现不再等效的情况。例如,如果x等于20,y等于5,下面两条语句的结果将不同:
其中第一条语句导致x的值为9,而第二条语句导致x的值为2。有疑问时,应使用多条赋值语句来简化表达式,而不要使用简化的运算符。
给变量赋值的语句是一个表达式,因为它生成一个值。因此,可以下面这种不同寻常的方式将赋值语句连在一起:
x = y = z = 7;
x = x / y + 5;
x /= y + 5;
在这条语句中,所有3个变量(x
、y
和z
)的值最后都为7。
在赋值之前,将首先计算赋值表达式的右边。因此,可以这样使用表达式语句:
int x = 5;
x = x + 2;
在表达式x
= x
+ 2
中,首先计算x
+2
;然后将结果(7)赋给变量x。
在编程中,使用表达式来修改变量的值是一项常见的任务。有几个专门用于这方面的运算符。
表2.4列出了这些赋值运算符及等效的表达式。
表2.4 赋值运算符
表达式 |
含义 |
---|---|
x += y |
x = x+y |
x -= y |
x = x-y |
x *= y |
x = x*y |
x /= y |
x = x/y |
另一种常见的编程任务将整型变量加1或减1。有专门用于完成这种运算的运算符:递增和递减运算符。对变量做递增运算意味着将它的值加1,做递减运算意味着将它的值减1。
递增运算符是++,递减运算符是−−。这些运算符位于变量名的前面或后面,如下所示:
int x = 7;
x++;
其中语句x++
将变量x
的值从7增加到8。
递增和递减运算符可放在变量名的前面或后面,这将影响表达式的结果。
如果递增和递减运算符位于变量名前面,则被称为前缀运算符;如果位于变量名后面,则被称为后缀运算符。
在简单表达式(如counts--;
)中,无论使用前缀还是后缀运算符,结果都相同,因此它们可以互换。然而,当递增和递减运算符被用于更复杂的表达式中时,选择前缀还是后缀运算符就至关重要。
请看下面的代码:
int x, y, z;
x = 42;
y = x++;
z = ++x;
上述3个表达式由于前缀和后缀运算符的差别而产生完全不同的结果。
使用后缀运算符时,先使用变量的值,再将变量递增或递减。因此,在y = x++
中,先将x
的值赋给y
,再将x
的值加1。
使用前缀运算符时,先将变量递增或递减,再使用变量的值。例如,在z = ++x
中,先将x
的值加1,再将x
的值赋给z
。
上述代码的最终结果是,y
等于42,z
等于44,x
等于44。
如果对此还不清楚,下面的例子再次通过注释描述了每一步的情况:
int x, y, z; // x, y, and z are declared
x = 42; // x is given the value 42
y = x++; // y is given x's value (42) before it is incremented
// and x is then incremented to 43
z = ++x; // x is incremented to 44, and z is given x's value
在特别复杂的表达式中使用递增和递减运算符时,很可能得到意外的结果。“在
x
自增之前将x
的值赋给y
”这一概念不再完全正确,因为Java总是先计算表达式右边的内容,然后再把结果赋给表达式左边的变量。Java在处理表达式之前会存储一些值,以便后缀运算符能够像本节介绍的那样工作。当包含前缀和后缀运算符的复杂表达式的结果不同于您的期望时,请将该表达式拆成多个语句,以简化它。
Java有几种可用于对变量之间、变量和字面量(或其他类型的信息)之间进行比较的运算符。
这些运算符用于返回布尔值(true
或false
)的表达式,表达式的返回值取决于比较的结果是真还是假。表2.5列出了这些比较运算符。
表2.5 比较运算符
运算符 |
含义 |
例子 |
---|---|---|
= = |
相等 |
x==3 |
!= |
不等 |
x!=3 |
< |
小于 |
x<3 |
> |
大于 |
x>3 |
<= |
小于等于 |
x<=3 |
>= |
大于等于 |
x>=3 |
下面的例子演示了比较运算符的用法:
boolean isHip;
int age = 37;
isHip = age < 25;
表达式age<25
的结果为true
还是false
取决于age
的值。由于这里的age
为37(比25大),因此isHip
为布尔值false
。
结果为布尔值的表达式(如比较运算)可以被组合成更加复杂的表达式。这是通过逻辑运算符来实现的,逻辑运算符用于逻辑组合:AND
、OR
、XOR
和逻辑NOT
。
对于AND
组合,可使用逻辑运算符&
或&&
。当两个布尔表达式通过&
或&&
组合在一起后,仅当两个布尔表达式都为真时,整个表达式的结果才为true
。
请看下面的例子:
boolean extraLife = (score > 75000) & (playerLives < 10);
这个表达式将两个比较表达式(score
> 75000
和playerLives
<10
)组合在一起。如果这两个表达式都为真,则true
被赋给变量extraLife
;在其他情况下,false
被赋给extraLife
。
&
和&&
之间的差别在于Java对组合表达式所做的工作量。如果使用&
,则不管什么情况下,&
两边的表达式都将被计算;如果使用&&
,则当左边的表达式为false
时,将不计算右边的表达式。
因此,&&
的效率更高,因为它不做不必要的工作。在前面的示例中,如果score
不比75000大,就根本不需要考虑playLives
是否小于10。
对于OR
组合,可使用逻辑运算符|或||。如果运算符两边的任何一个布尔表达式为真,则组合表达式的结果为true
。
请看下述示例:
boolean extralife = (score > 75000) || (playerLevel == 0);
该表达式合并了两个比较表达式:score
> 75000
和playerLevel
= = 0
。只要这两个表达式中的任何一个为真,则true
被赋给变量extraLife
;仅当这两个表达式都是false
时,false
才被赋给extraLife
。
注意,这里使用的是||,而不是|。因此,如果score > 75000
为true,则extraLife
将被设置成true,而根本不会计算第二个表达式。
用于XOR
合并的逻辑运算符只有一个:^。仅当被合并的两个布尔表达式的值相反时,整个表达式的结果才为true;如果两个表达式都是true或都是false,则^运算符的结果为false
。
NOT
组合使用逻辑运算符!,后面跟一个表达式。它对布尔表达式的值求反,这与用负号来改变数字的符号相同。例如,如果age
<25
的结果为true
,则!(age<25)
的结果将为false
。
首次见到这些逻辑运算符时,可能觉得它们完全不符合逻辑。在本周余下的课程中,您将大量地使用它们,尤其是在第5章。
当表达式中有多个运算符时,Java有一套优先级用来判断运算符的执行顺序。在许多情况下,优先级决定了整个表达式的最终值。
例如,请看下面的表达式:
y = 6 + 4 / 2;
变量y
的值为5还是8取决于哪个算术运算先被处理。如果先计算表达式6+4
,则y
的值为5;否则为8。
通常,从先到后的顺序如下:
1.递增和递减运算;
2.算术运算;
3.比较运算;
4.逻辑运算;
5.赋值运算。
如果两个运算的优先级相同,则左边的比右边的先被处理。表2.6列出了Java中众多运算符的优先级。排在越前面的运算符的优先级越高。
表2.6 运算符优先级
运算符 |
说明 |
---|---|
. [] () |
句点(.)用来访问对象和类中的方法和变量;方括号([ ])用于数组;圆括号(( ))用来将表达式分组 |
++ −− ! ~ instanceof |
instanceof运算符返回true或false值,这取决于该对象是否属于指定的类或其子类的一个实例 |
new(type)expression |
new运算符用来创建类的新实例;其中( )用于将值转换为另一种类型 |
* / % |
乘法、除法和求模运算 |
+ - |
加减 |
<< >> >>> |
按位左移和右移 |
< > <= >= |
关系比较 |
== != |
相等和不等 |
& |
AND |
^ |
XOR |
¦ |
OR |
&& |
逻辑AND |
¦¦ |
逻辑OR |
?: |
三目运算符 |
= += -= *= /= %= ^= |
各种赋值运算 |
&= ¦ = <<= >>= >>>= |
其他赋值运算 |
表2.6中的多个运算符都将在本周后面的课程中介绍。
回过头来看表达式y =6 + 4 / 2
。表2.6表明,除法先于加法计算,因此y
的值为8。
要改变表达式求值的顺序,可以用圆括号将需要先计算的表达式括起。可以嵌套圆括号以确保按所需的顺序对表达式进行求值——最里边的圆括号内的表达式最先被计算。
下述表达式的结果为5:
y = (6 + 4) / 2
因为先计算6 + 4
,得到10,然后再除以2,最后的结果为5。
圆括号还可以提高表达式的可读性。如果不能一眼看出表达式的优先级,可以添加圆括号来强制转换为希望的优先级,使语句更容易理解。
正如本章前面指出的,在数学领域之外,运算符+有另一种功能:拼接多个字符串。
拼接(concatenate)指的是将两样东西连接到一起。不知道什么原因,在编程领域选择了这个动词来描述合并字符串的操作——它从paste、glue、affix、combine、link、smush together和conjoin等中脱颖而出。
在一些例子中,您已经看到了像下面这样的语句:
String brand = "Jif";
System.out.println("Choosy mothers choose " + brand);
这两行代码将显示下述文本:
Choosy mothers choose Jif
运算符+将字符串、其他对象和变量合并为一个字符串。在上面的例子中,字面量Choosy mothers choose与String
对象brand
的值合并在一起。
在Java中,拼接运算符的用法很简单,因为运算符将任何变量类型和对象值都作为字符串进行处理。如果拼接运算的任何一个部分是String
或String字面量,则其他所有元素都将被作为字符串进行处理:
System.out.println(4 + " score and " + 7 + " years ago");
这将产生文本输出4 score and 7 years ago,就像整数字面量4和7是字符串一样。
也可以用简化运算符+=来在字符串末尾添加内容。例如,请看下面的表达式:
myName += " Jr.";
这个表达式等效于:
myName = myName + " Jr.";
在这个例子中,+=修改了myName
的值(原来可能是Robert Downey)——在后面添加Jr.(因此变成Robert Downey Jr.)。
表2.7列出了本章介绍的运算符,以对本章的内容做一总结,请仔细地查看。
表2.7 运算符小结
运算符 |
含义 |
---|---|
+ |
加 |
− |
减 |
* |
乘 |
/ |
除 |
% |
求模 |
< |
小于 |
> |
大于 |
<= |
小于等于 |
>= |
大于等于 |
== |
相等 |
!= |
不等 |
&& |
逻辑与 |
¦¦ |
逻辑或 |
! |
逻辑非 |
& |
与 |
¦ |
或 |
^ |
异或 |
= |
赋值 |
++ |
递增 |
-- |
递减 |
+= |
相加然后赋值 |
-= |
相减然后赋值 |
*= |
相乘然后赋值 |
/= |
相除然后赋值 |
%= |
求模然后赋值 |
任何打开俄罗斯套娃的人,在找到最小的洋娃娃后,都难免会失望。
在本章中,您看到了Java中最小的洋娃娃。语句和表达式让您能够创建高效的方法,进而创建出高效的对象和类。
在本章中,您学习了如何创建变量并给它赋值,还学习了使用字面量来表示数字、字符和字符串值以及如何使用运算符。在下一章中,您将使用这些技术来开发类。
问:如果将一个超出变量取值范围的整数值赋给该变量,将发生什么情况?
答:从逻辑上说,您可能认为该变量将被转换为与之接近的更大类型,但情况并非如此。相反,将发生溢出,即从一个极端回到另一个极端。例如,byte
变量的值从127(可接受的值)变到128(不可接受)时,将转到最小的可接受值,即−128,然后往上增大。您并不希望程序中发生溢出,因此将值赋给数值变量时,不应超过其所属数据类型的取值范围。
在计算机的内存很少,每个字节的内存都很金贵时,使用byte
等较短的数据类型显得很重要。当前,计算机配置了大量内存和硬盘空间,其大小以太字节(Terabyte)计,因此最好使用较长的数据类型,如int
,这样可确保变量有足够的空间存储所有可能的值。
问:为什么Java包含所有用于数学运算和赋值的简化运算符?它们不太好阅读。
答:Java的语法是基于C++的,而后者又是基于C的(又是一个俄罗斯套娃)。C是一种专家语言,它更重视功能,而不是可读性,简化运算符是这种设计思想的产物之一。并不是非得在程序中使用它们,因为可能采用其他方式。如果愿意,可以在程序中尽量避免使用它们。
问:第1章的类MarsRobot和MarsApplication不包含package语句,这是否意味着它们不会放在包中?
答:所有Java类都归属于某个包。类包含package
语句时,它将归属于指定的包;本章创建的类都归属于com.java21days
。
不包含package
语句的类归属于未命名的默认包。虽然可以在这个未命名的包中创建类,但对于使用Java创建的每个类,最好都指定它所属的包。第1章没有这样做是出于简化考虑。
请回答下述3个问题,以复习本章介绍的内容。
1.下面哪个是合法的布尔值?
A."false"
B.false
C.10
2.下面哪条不属于Java的变量命名约定?
A.除第一个单词外,变量名中其他单词的首字母都大写
B.变量名的第一个字母小写
C.所有字母都大写
3.下面哪种数据类型的取值范围为−32768~32767?
A.char
B.byte
C.short
1.B。在Java中,布尔值只能是true或false。用引号将这些值括起时,它们将被视为String,而不是布尔值。
2.C。常量名全部大写,以便将其与其他变量区分开来。
3.C。这是基本数据类型short的取值范围。
下面的问题是Java认证考试中可能出现的问题,请回答该问题,而不要查看本章的内容。
下面哪组数据类型能够存储3000000000(30亿)?
A.short
、int
、long
、float
B.int
、long
、float
C.long
、float
D.byte
答案见本书的配套网站www.java21days.com。单击链接02,再单击链接Certification Practice。
为巩固本章介绍的知识,请尝试完成下面的练习。
1.创建一个程序,计算14000美元的投资在3年后值多少。假设第一年增值40%,第二年损失1500美元,第三年又增值12%。
2.编写一个程序,它显示两个数字,并使用/
和%
来显示它们相除后的商和余数。输出时,使用转义符\t
来输出制表符,以便将商和余数分开。
解决方案见本书的配套网站www.java21days.com。