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

978-7-115-52537-6
作者: 武春岭 沈廷杰
译者:
编辑: 李莎
分类: Java

图书目录:

详情

针对目前开发行业对Java开发工具应用的技能需求以及计算机类专业对Java编程的基本要求,本书以“学习目标→任务引导→相关知识→任务实施→综合训练”为主线,在介绍程序语法的基础上,以小项目开发为实践落脚点,做到学练结合,提高学习效率:通过“学习目标”和“任务引导”,让读者先了解要解决的问题;然后详细讲解相关知识,帮助读者奠定技术基础;进而在“任务实施”引导读者完成上机操作,体现学以致用,并通过“拓展训练”帮助读者进一步提高编程技术和能力;最后通过“综合训练”梳理重要知识点,促进读者对重要内容的掌握。 本书整体上采用“项目引导与驱动”模式,将枯燥的程序语法学习融入具体项目案例,这有利于激发读者学习兴趣,提升学习效果。此外,本书案例源自实际生活,并参考近期Java编程岗位的技能需求,结构合理,实用性强。 本书可作为高职院校计算机类专业或电子信息类专业Java程序设计教材,也可作为成人高等学校和其他培训机构的教材,还可以作为零基础学习Java读者的参考图书。

图书摘要

面向对象程序设计Java版

武春岭 沈廷杰 主编

朱崇来 副主编

人民邮电出版社

北京

图书在版编目(CIP)数据

面向对象程序设计:Java版 / 武春岭,沈廷杰主编.--北京:人民邮电出版社,2020.5

ISBN 978-7-115-52537-6

Ⅰ.①面… Ⅱ.①武…②沈… Ⅲ.①JAVA语言-程序设计-高等职业教育-教材 Ⅳ.①TP312.8

中国版本图书馆CIP数据核字(2019)第253879号

◆主 编 武春岭 沈廷杰

副主编 朱崇来

责任编辑 李莎

责任印制 王郁 马振武

◆ 人民邮电出版社出版发行 北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

北京鑫正大印刷有限公司印刷

◆ 开本:787×1092 1/16

印张:31.25  2020年5月第1版

字数:479千字  2020年5月天津第1次印刷

定价:79.00元

读者服务热线:(010)81055410 印装质量热线:(010)81055316

反盗版热线:(010)81055315

广告经营许可证:京东工商广登字20170147号

内容提要

针对目前开发行业对Java开发工具应用的技能需求以及计算机类专业对Java编程的基本要求,本书以“学习目标→任务引导→相关知识→任务实施→综合训练”为主线,在介绍程序语法的基础上,以小项目开发为实践落脚点,做到学练结合,提高学习效率:通过“学习目标”和“任务引导”,让读者先了解要解决的问题;然后详细讲解相关知识,帮助读者奠定技术基础;进而在“任务实施”引导读者完成上机操作,体现学以致用,并通过“拓展训练”帮助读者进一步提高编程技术和能力;最后通过“综合训练”梳理重要知识点,促进读者对重要内容的掌握。

本书整体上采用“项目引导与驱动”模式,将枯燥的程序语法学习融入具体项目案例,这有利于激发读者学习兴趣,提升学习效果。此外,本书案例源自实际生活,并参考近期Java编程岗位的技能需求,结构合理,实用性强。

本书可作为高职院校计算机类专业或电子信息类专业Java程序设计教材,也可作为成人高等学校和其他培训机构的教材,还可以作为零基础学习Java读者的参考图书。

编委会名单

主任:王秉科(中国通信工业协会会长)

副主任:武马群 徐玉彬

委员:王永乐 王隆杰 史宝会 史小英 蒋丛永

许彪 罗保山 周观民 刘昉 武凤翔

王世刚 彭建盛 于大伟 龙天才 杨智勇

李圣良 陈中原 曾德贵 顾卫杰 王璐烽

向春枝 成红雨 苏命峰 陈运军 王超

吴交树 黄君羡 徐义晗 王喜 杜恒

张占启 黄彬 雷惊鹏 杨云 赵建超

主编:沈廷杰 武春岭 王敬华

副主编:朱崇来

合作企业:北京华道日志科技有限公司

启明星辰信息技术集团股份有限公司

锐捷网络科技有限公司

前言

根据我们针对计算机相关岗位招聘需求信息的调研,关于编程语言,高职院校的计算机相关专业学生应至少掌握或接触过一门面向对象的高级程序设计语言。学生掌握相关知识技能后,才能更好地胜任对应的工作岗位。而面向对象程序设计语言,从最近3年的TIOBE编程语言排行榜来看,Java一直处于前几名。所以,本书选取的编程语言是Java。本书在编写的过程中,“学习目标”是来自近期的实际岗位需求信息,由此梳理和整合的相关知识技能会更贴近岗位需求。

本书是针对Java的面向对象程序设计教材,既适合高职院校学生学习使用,也适合高职教师授课时参考,同时还可作为Java编程语言的初学者用书。本书的使用思路:根据所在高职院校学生现状和专业人才培养方案,对照本书学习目标,选取本书合适的章节进行教学大纲、教学计划等设计;选取对应章节合适的知识作为教学点,进行教学方案设计;选取对应章节的实训案例,指导学生练习。学生除了可以根据教师教授的内容进行复习和练习外,还可以挑选一些感兴趣的技术点学习,并就对应的案例进行练习。其他Java初学者,可以参考本书的目录按序学习和练习。

本书由重庆电子工程职业学院武春岭、沈廷杰任主编并执笔,朱崇来任副主编。内容共分10章,其中,沈廷杰编写第1章~第4章;武春岭编写第5章~第7章;朱崇来编写第8章~第10章。全书涵盖初识Java、控制结构、方法与数组应用、类与对象应用、反射机制与常用类应用、数据结构应用、集合应用、文件操作应用、线程应用、网络编程应用和软件测试应用。项目贯穿所有章节知识点,以“学习目标→任务引导→相关知识→任务实施→综合训练”为脉络,多方位提高学生的编程技术和能力,让学生得以掌握整个项目设计实施过程。其中,“学习目标”是当前行业实际岗位需求中的主流要求;“任务引导”是章节知识与技能的概要性导入;“相关知识”是章节目标对应所需的技能基础;“任务实施”是强化训练的案例题目与动手操作;“综合训练”是对重要知识的再梳理。全书内容精简、重点突出。

由于作者水平有限,书中难免存在不足之处,恳请广大读者不吝指正,我们将在再版时及时改进。若您在学习过程中遇到困难或疑问,可发送电子邮件至zhangtianyi@ptpress.com.cn。

编者

第1章 初识Java

学习目标

• 能够搭建Java开发环境。

• 掌握Java注解方法。

• 能够利用Java基本数据类型进行表达式运算。

任务引导

Java是一种可以开发跨平台应用软件的面向对象程序设计语言。Sun公司(已被Oracle收购)于1995年5月推出了Java程序设计语言和Java平台。在这二十多年的时间里,Java技术因为其具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人计算机、数据中心、游戏控制台、科学超级计算机、移动电话和互联网,因而拥有广大的开发者群体。在全球云计算和移动互联网的产业环境下,Java更具备了显著优势和广阔前景。

Java的基础知识包括Java的基本数据类型、常量和变量以及运算符和表达式。如果把程序比作房子,那么这些基础知识就类似于砖、瓦和水泥,对这些基础知识的深刻理解是编写高质量程序的基础。

相关知识

1.1 计算机语言

计算机语言是指用于人与计算机之间通信的语言。为了使计算机完成各项工作,就需要有一套用于编写计算机程序的数字、字符和语法规则,由这些字符和语法规则组成的计算机的各种指令(或各种语句),就是计算机能理解的语言。

1.1.1 机器语言

机器语言是指一台计算机全部的指令集合。

机器语言是通常所说的第一代计算机语言,由二进制数“0”和“1”组成,并将这一串串由“0”和“1”组成的指令序列,交给计算机执行。

因而使用机器语言时,程序员就需要知道每个指令对应的“0”“1”序列,而这单靠记忆几乎是不可能完成的。在程序运行过程中,如果出错需要修改,那更是难上加难。

另外,每种类型的计算机,其指令系统各不相同。针对不同类型的计算机,完成相同功能的程序需要使用不同的指令系统编写。其实不少高级语言仍然没有解决类似的问题,但是Java的出现,在相当大的范围内解决了此问题,这就是Java的特性之一,即“一次编译,处处运行”。

上面提到了机器语言的诸多问题,不过正是因为这些问题,也说明了机器语言的一大好处——当面向特定类型的计算机时,机器语言的运行效率最高。

1.1.2 汇编语言

程序员使用机器语言编写程序是非常痛苦的,其中一个原因就是难以记住每个指令对应的“0”“1”序列。为了让程序员从大量的记忆工作中解脱出来。人们进行了一种有益的改进,用一些简洁的、有一定含义的英文字符串来替代特定指令的“0”“1”序列。例如,用“MOV”代表数据传递、“DEC”代表数据减法运算。对于计算机而言,这些冰冷的机器是不懂“MOV”这类汇编语言的,计算机只认识“0”“1”序列。这样,在计算机上就需要有一个专门的程序,负责把汇编语言翻译成二进制的机器语言,这种翻译程序就是汇编程序。

对程序员而言,从机器语言到汇编语言,犹如人们从结绳计数发展到使用数字符号计数,工作效率得到极大提高。因而汇编语言也被称为第二代计算机语言。

汇编语言实质上和机器语言是相同的,都是直接对硬件操作,只不过汇编语言的指令采用了英文缩写的标识符,更易于识别和记忆。

不论是机器语言还是汇编语言,所发出的每一个指令只能对应实际操作过程中的一个细微动作,例如移动、自增等,要实现一个相对复杂的功能就需要非常多的步骤。例如,要完成“小张去传达室取回信件”的编程任务,这两种语言只能将任务分解成“向前n米”“向后n米”“左转”“右转”“上n个台阶”“下n个台阶”“伸手”等细微动作之后,再发出相应的指令,因而完成这样的一个任务,就得要几十个步骤,工作量很大。

1.1.3 高级语言

从最初与计算机交流的痛苦经历中,人们意识到,应该设计一种这样的语言,其接近于数学语言或人的自然语言,同时又不依赖于计算机硬件,编出的程序能在所有计算机上运行。

经过努力,1954年,第一个完全脱离计算机硬件的高级语言——FORTRAN诞生。目前,影响较大、使用较广泛的高级语言有Java、C语言、C++、C#。另外还有一些其他类型的语言,比如智能化语言(LISP、Prolog、CLIPS……)、动态语言(Python、PHP、Ruby……)等。

1.C语言

提到高级语言,必须要重点介绍一下C语言。

C语言是一种计算机程序设计语言,它既具有高级语言的特点,又具有汇编语言的特点。1972年由美国贝尔实验室推出C语言。1978年以后,C语言先后被移植到大型、中型、小型及微型机上。C语言功能非常强大,使用C语言既可以编写不依赖计算机硬件的应用程序,也可以编写操作系统(在操作系统及需要对硬件进行操作的场合,使用C语言明显优于其他高级语言)。C语言的应用范围广泛,单片机、嵌入式系统、二维动画、三维动画、游戏开发、数据业务处理等多方面都能看到它的身影。

为了方便和Java进行比较,下面简要介绍C语言的一些重要特点。

(1)C语言(习惯上称为中级语言)把高级语言的基本结构和语句与低级语言的实用性结合起来,它可以像汇编语言一样对位、字节和地址进行操作。

(2)C语言使用指针直接进行靠近硬件的操作,对于程序员而言显得更加灵活,但同时也给程序带来了安全隐患。在构建Java时,参考了C语言的诸多优势,但为了安全性,就取消了指针操作。

2.C++

C++是具有面向对象特性的C语言。

面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。当今,程序开发思想已经全面从面向过程(C语言)分析、设计和编程发展到面向对象的模式。

通过面向对象的方式,将现实世界的事务抽象成类和对象,帮助程序员实现对现实世界的抽象与建模。通过面向对象的方法,采用更利于人理解的方式对复杂系统进行分析、设计与编程。

3.C#

C#是一种面向对象的、运行于.NET Framework之上的高级程序设计语言。C#与Java惊人的相似(单一继承、接口、编译成中间代码再运行),就如同Java和C语言在基本语法上类似一样。在语言层面,C#是微软公司.NET Windows网络框架的主角。

和汇编语言相比,高级语言(第三代计算机语言)将许多硬件相关的机器指令合并成完成具体任务的单条高级语言,与具体操作相关的细节(如寄存器、堆栈等)被透明化。程序员只要会操作单条高级语句即可,即使没有深入掌握操作系统级别的细节,也可以开发出程序。

1.2 Java发展史

1.2.1 Java的诞生

1995年5月23日,在Sun World大会上,Sun公司第一次公开发布Java和HotJava浏览器。在这个会议上,网景公司(当时该公司浏览器占据浏览器市场份额的领先地位)宣布将在其浏览器中支持Java,随后一系列公司表示了对Java的支持,使Java很快成为一个极具发展潜力的高级语言。

1.2.2 JDK 1.0发布

1995年,Sun公司推出的Java只是一种语言,而要想开发复杂的应用程序,必须要有一个强大的开发支持库。

1996年1月,Sun公司发布了JDK 1.0,它包括两部分:运行环境(Java Runtime Environment,JRE)和开发环境(Java Development Kit,JDK)。在运行环境中包括了核心应用程序接口(Application Programming Interface,API)、集成API、用户界面API、发布技术和Java虚拟机(Java Virtual Machine,JVM)5个部分,而开发环境还包括了编译Java程序的编译器(java compiler,javac)。在JDK 1.0时代,Java库显得比较单薄,不够完善。随着JDK的逐步升级,它为开发人员提供了一个强大的开发支持库。

1.2.3 Java 2问世

1998年12月,Sun公司发布了Java历史上非常重要的一个JDK版本——JDK 1.2,并开始使用“Java 2”这一名称。从JDK 1.2发布开始,Java踏入了飞速发展的时期。

在Java 2时代,Sun公司对Java进行了很多革命性的改变,而这些革命性的变化一直沿用到现在,对Java的发展形成了深远的影响。

Java 2平台包括标准版(Java 2 Standard Edition,J2SE)、企业版(Java 2 Enterprise Edition,J2EE)和微缩版(Java 2 Micro Edition,J2ME)3个版本。

• J2SE:Java 2标准版包含构成Java核心的类,例如数据库连接类、接口定义类、输入/输出类、网络编程类。

• J2EE:Java 2企业版除了包含J2SE中的类外,还包含用于开发企业级应用的类,例如EJB、Servlet、JSP、XML、事务控制。

• J2ME:Java 2微缩版包含J2SE中一部分类,用于消费类电子产品的软件开发,例如寻呼机、智能卡、手机、PDA、机顶盒。

此后,还发布了以下主要版本的Java。

2000年5月,J2SE 1.3发布。

2002年2月,J2SE 1.4发布。

1.2.4 JavaSE 5.0发布

2004年9月30日,J2SE 1.5发布,成为Java发展史上的又一里程碑。为了表示该版本的重要性,J2SE 1.5更名为JavaSE 5.0。

在JavaSE 5.0中,主要包含以下主要新特性。

• 泛型。

• 增强for循环。

• 自动拆箱和装箱。

• 类型安全的枚举。

• 静态导入。

• Annotation注解。

1.2.5 JDK 7.0发布

2011年7月,JDK 7.0发布,增加了一些新的功能。例如,原来switch结构的条件中只能包含byte、short、int、char类型,从7.0开始,其中可以包含字符串了。

1.2.6 JDK 8.0发布

2014年3月,JDK 8.0发布。该版本引入了新的语言特性——Lambda表达式,它可为Java提供匿名函数类型,用户可以将函数作为一个方法的参数,或将代码作为数据。Lambda表达式能够使表达单一方法接口的实例更紧凑;完善重复注释功能,即可以在同一申明类型(类、属性或方法)中多次使用同一个注解,可读性更强;改进了类型注解,使其可以应用在任何地方。Lambda表达式与可插入的类型系统配合使用,使代码的类型检查更加完善,改进了泛型类型推断。使用JDK 7.0版本创建泛型实例时的类型推断是有限制的:只有构造器的参数化类型在上下文中被显著声明,才能使用类型推断,否则不能使用。而JDK 8.0版本支持通过方法上下文推断泛型目标类型,也支持在方法调用链路当中,泛型类型推断传递到最后一个方法,并新增方法参数反射。用户可以将方法参数的元信息存储到编译完的.class文件中,使程序可以在运行时通过反射来获取参数的元信息。

1.2.7 JDK 9.0发布

2017年7月,JDK 9.0发布。在JavaSE 9.0中,主要包含以下主要新特性。

• 模块化的源代码。

• 轻量级的JSON API。

• 系统进程管理。

• 完善竞争锁。

• 分段代码缓存。

• 智能Java编译器。

1.2.8 JDK 10.0发布

2018年3月,JDK 10.0发布。在JavaSE 10.0中,主要包含以下主要新特性。

• 局部变量类型推断。

• 整合JDK代码仓库。

• 统一的垃圾回收接口。

• 并行全垃圾回收器G1。

• 应用程序类数据共享。

• 线程局部管控。

• 移除Native-Header自动生成工具。

• 额外的Unicode语言标签扩展。

• 备用存储装置上的堆分配。

• 根证书认证。

1.3 Java的特点

要想系统地说明Java的特点,需要大篇幅、长时间地介绍。以下是Java的主要特点。

• Java是简单的。

• Java是面向对象的。

• Java是分布式的。

• Java是健壮的。

• Java是安全的。

• Java是平台无关的。

• Java是可移植的。

• Java是解释型的。

• Java是高性能的。

• Java是多线程的。

• Java是动态的。

随着本书内容的深入,会逐步学习到这些具体的内容,这里仅就以下3点做简要介绍。

1.3.1 Java是面向对象的

面向对象其实是现实世界模型的自然延伸,现实世界中任何实体都可以看作对象,对象之间通过消息相互作用。

另外,现实世界中任何实体都可归属于某类事物,任何对象都是某一类事物的实例。

传统的过程式编程语言以过程为中心,以算法为驱动(程序=算法+数据)。面向对象编程语言则以对象为中心,以消息为驱动(程序=对象+消息)。

Java是典型的面向对象语言,具体面向对象的概念和应用,会在后面的章节中详细介绍。

1.3.2 Java是平台无关的

所谓Java是平台无关的语言,是指用Java编写的应用程序,编译成字节码文件(.class后缀)后,不用修改就可在不同的软/硬件平台上运行。

平台无关有两种:源代码级和目标代码级。C语言和C++具有源代码级平台无关性(没完全做到),表明用C语言或C++写的程序不用修改,在不同的平台上重新编译后,就可以在对应平台上运行。而Java是目标代码级的平台无关,使用JDK编译成的字节码文件,只要在安装有Java虚拟机的平台上就可以运行,这就是通常说的“一次编译,处处运行”。

1.3.3 Java语言是健壮的

强类型机制、丢弃指针、垃圾回收机制、异常处理等是Java健壮性的重要保证,对指针的丢弃是Java明智的选择。

Java是强类型的语言。Java要求使用显式的方法声明,这样编译器就可以发现方法调用错误,保证程序的可靠性。

Java丢弃了指针。这样可以避免内存的非法访问,虽然牺牲了程序操作的灵活性,但对程序的健壮性而言,不无裨益。

Java的垃圾回收机制是Java虚拟机提供的管理内存的机制,用于在空闲时间以不定时的方式动态回收无任何引用的对象所占据的内存空间。

Java提供了异常处理机制,程序员可以把一组可能出错的代码放在一个地方,针对可能的错误(异常)编写处理代码,简化错误处理过程,便于恢复。

1.4 Java程序工作原理

1.4.1 Java虚拟机

Java虚拟机(Java Virtual Machine,JVM)不是一台真实的机器,而是想象中的机器,通过模拟真实机器来运行Java程序。

虽然是模拟出来的机器,但Java虚拟机同样有硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。

Java虚拟机是Java程序的运行环境,Java程序运行在这个抽象的Java虚拟机上,这也是Java最具吸引力的特性之一。

前文提到过,Java的一个重要特点就是目标代码级的平台无关性,接下来将从原理上进一步说明为什么Java具有这样的平台无关性。实现Java“一次编译,处处运行”的关键就是使用了Java虚拟机。

例如,使用C语言开发一个类似计算器的软件,如果想要这个软件在Windows平台上运行,则需要在Windows平台上编译成目标代码,这个计算器的目标代码只能在Windows平台上运行。而如果想让这个软件能在Linux平台上运行,则必须在对应的平台上编译,产生针对该平台的目标代码,才可以运行。

对Java而言,则完全不是这样的。用Java编写的计算器程序(.java后缀)经过编译器编译成字节码文件,这个字节码文件不是针对具体平台的,而是针对抽象的Java虚拟机的,是在Java虚拟机上运行的。在不同的平台上,安装不同的Java虚拟机,这些不同的Java虚拟机屏蔽了各个不同平台的差异,从而使Java程序(字节码文件)具有平台无关性。也就是说,Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行,具体原理如图1.1所示。

在理解了Java虚拟机的基础上,接下来介绍Java程序工作原理。如图1.2所示,Java字节码文件先后经过Java虚拟机的类装载器、字节码校验器和解码器,最终在操作系统平台上运行。各部分的主要功能描述如下。

• 类装载器,其主要功能是为执行程序寻找和装载所需要的类,就是把字节码文件装到Java虚拟机中。

• 字节码校验器,其功能是对字节码文件进行校验,保证代码的安全性。字节码校验器负责测试代码段格式并进行规则检查,检查伪造指针、违反对象访问权限或试图改变对象类型的非法代码。

• 解码器,具体的平台并不认识字节码文件,最终起作用的还是这个解码器,它将字节码文件翻译成所在平台能识别的东西。

1.4.2 垃圾回收机制

在C++中,程序结束运行之前对象会一直占用内存,且程序员明确释放之前不能将其所占内存分配给其他对象。而Java的处理方式不同,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾。

Java虚拟机提供了一个系统级线程(垃圾回收器线程),它自动跟踪每一块被分配出去的内存空间,自动释放被定义成垃圾的内存。

垃圾回收机制能自动释放内存空间,减轻程序员编程的负担,这是Java虚拟机具有的一个显著优点。在没有垃圾回收机制的时候,可能要花许多时间来解决释放无用内存的问题,而用Java编程的时候,靠垃圾回收机制可大大缩短时间。

垃圾回收机制是一个系统级的线程,它给程序员带来好处的同时,也存在着影响系统性能的问题,因为它要追踪分配的内存,释放没用的内存,而这个过程需要花费系统资源。

程序员可以调用System.gc()这个方法通知Java虚拟机释放无用资源,但Java虚拟机会选择在合适的时候释放无用资源,具体释放的时间,不是程序员调用System.gc()的时刻,而是Java虚拟机决定的,程序员不能精确控制和干预。

1.5 Java SE的结构

Java SE是Java的基础,它包含Java基础、JDBC数据库操作、I/O(输入/输出)、网络通信、多线程等技术。

JDK是一个Java应用程序的开发环境。它由两部分组成,下层是处于操作系统层之上的运行环境,上层由编译工具、调试工具和运行Java应用程序所需的工具组成。

JDK主要包含以下基本工具(仅列举部分常用的工具)。

• javac:编译器,将源程序转成字节码文件。

• java:执行器,运行编译后的字节码文件。

• javadoc:文档生成器,从源码注释中自动产生Java文档。

• jar:打包工具,将相关的类文件打包成一个文件。

JDK包含以下常用类库。

• java.lang:系统基础类库,其中包括字符串类String等。

• java.io:输入输出类库,进行文件读写时需要用到。

• java.net:网络相关类库,进行网络通信时会用到其中的类。

• java.util:系统辅助类库,编程中经常用到的集合属于这个类库。

• java.sql:数据库操作类库,连接数据库、执行SQL语句、返回结果集需要用到该类库。

• javax.servlet:JSP、Servlet等使用到的类库,是Java后台技术的核心类库。

1.6 标识符和关键字

标识符是编程时使用的名字。使用某个东西时,要用到它的名字来标识它,给这个东西起的名字,也需要有一定的规则,不能随便乱起名字。而关键字是事先定义好的、有特殊意义的标识符。

1.6.1 标识符

Java对各种变量、方法和类等要素命名时使用的字符序列称为标识符。

Java标识符有如下命名规则。

(1)标识符由字母、数字、下划线“_”、美元符号“$”组成,并且首字符不能是数字。

(2)不能把Java关键字作为标识符。

(3)标识符没有长度限制。

(4)标识符对大小写敏感。

在企业的面试题里,常会出现这样的题目,下面的标识符中哪些是非法的?

stuAge、*stuName、ount、3heartNum、public、x+y、_carSpeed、length10

*stuName是非法的,原因是不能含“*”;3heartNum是非法的,原因是首字符不可以是数字;public是非法的,原因是不可以是Java关键字;x+y是非法的,原因是不能含“+”。其他的标识符都是合法的。

作为一名程序员,写的程序中标识符不仅要合法,而且要简短且能清楚地表明含义,同时还要符合Java标识符的命名规范,这样可以让程序规范、易读。下面列举了不同类型(后面会详细介绍)标识符的命名规则。

• 对于变量名和方法名,要求第一个单词应以小写字母作为开头,后面的每个单词则都要以大写字母开头,例如stuAge、sendMessage。

• 对于类名,它和变量名、方法名的区别在于,第一个单词的首字母也需要大写,如果类名称中包含单词缩写,则这个缩写词的每个字母均应大写,例如XMLModule。另外,由于类是用来代表对象的,所以在命名类时应尽量选择名词。

• 常量标识符应该都使用大写字母,并且指出该常量完整的含义。如果一个常量名称由多个单词组成,则应该用下划线来分割这些单词,例如MAX_VALUE。

1.6.2 关键字

Java关键字对Java编译器有特殊的意义,它们用来表示一种数据类型或者表示程序的结构,关键字不能用作变量名、方法名、类名和包名。

大多数的编辑器(例如Eclipse和UltraEdit,不含记事本)和集成开发环境(Eclipse和MyEclipse)都会用特殊的方式(通常用蓝色)把Java关键字标识出来。

Java关键字都是小写的英文字符串,goto这个标识符虽然很少使用,但也作为Java关键字进行保留,需要注意。图1.3列出了所有的Java关键字。

1.7 Java注解

1.7.1 Java注解

从JDK 1.5开始,Java引入了源代码中的注解这一机制。注解使得Java源代码不但可以包含功能性的实现代码,还可以添加元数据。注解看起来有点类似于代码中的注释,所不同的是注解不是为了说明代码功能,而是为了实现程序功能。

在介绍注解的概念前,首先介绍元数据的概念。所谓元数据,就是描述数据的数据。举个例子,比如一张图片,图片的内容为主体数据,是需要展现给图片浏览者看到的信息,而图片的创建日期这类信息就是元数据,是用来描述图片内容这个数据的数据。

元数据有什么用呢?还是以图片创建日期为例,假设我现在想找一张2013年8月1日拍的照片,在计算机中就可以根据这个创建日期查找到该照片。再举一个例子,在编写Java注释的时候,如果按照某种特定的规范编写Java注释,则可以通过javadoc工具将这些注释自动生成帮助文档,这些按规定编写的Java注释就属于元数据,用来描述程序。我们可以用元数据来创建文档、跟踪代码,执行编译时检查格式,并可以用其代替原系统中原有的配置文件。

Java注解是Java代码里的特殊标记,为我们在代码中添加用Java程序无法表达的额外信息提供了一种形式化的方法,使我们可以在未来某个时刻方便地使用这些被注解修饰的程序元素(这些程序元素包括类、属性、方法等)。

注解看起来有些像注释,但其和注释还是有显著区别的。虽然注解和注释都属于对代码的描述,但注释的作用只是简单地描述程序信息,方便开发者再次阅读,不会被程序所读取,而注解则是Java代码中的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理,两者作用相差很大。

通过使用注解,程序开发人员可以在不改变程序原有逻辑的情况下,在源代码中加入一些补充信息,代码分析工具、开发工具和部署工具可以通过这些补充信息进行验证和部署。下面的代码展示了注释和注解。

刚才介绍了Java注解的基本概念,现在来看一下Java注解的语法。使用注解时要在其前面加一个“@”符号,表明后面的内容为注解。Java注解有3种形式。

• 不带参数的注解:@Annotation,例如@Override。

• 带一个参数的注解:@Annotation(参数),例如@SuppressWarings(value="unused")。

• 带多个参数的注解:@Annotiation({参数1,参数2,参数3...}),例如@MyTag(name:="jhon", age=20)。

1.7.2 内建注解

在Java的java.lang包中,预定义了3个注解,它们分别是限定重写父类方法的@Override注解,标记已过时的@Deprecated注解和抑制编译器警告的@SuppressWarnings注解,通常称这3个注解为内建注解或基本注解。

@Override注解

@Override注解被用于标注方法,被该注解标注的方法是重写了父类的方法,起到了确定的作用。下面通过一个例子演示@Override注解的作用。

假设“租车系统”中Vehicle类和Truck类的代码如下,其中Truck类继承自Vehicle类,且重写了Vehicle类的drive()方法(根据需求这个方法必须要重写)。

注:“租车系统”是贯穿全书的一个案例,是围绕车辆的特性和行为进行的类的设计和实现,以下代码仅演示@Override注解的作用。本书3.6节将详细介绍“租车系统”的相关知识。

编译、运行Truck类,程序可以按用户需求执行。但是有可能程序员在写Truck类的代码时,误将drive()写成了driver(),然而在执行t1.drive();语句时,因为drive()方法并未被重写,因此t1.drive()调用的还是Vehicle类的drive()方法。不幸的是,这种错误程序编译时是不会报错的,即使在运行时如果不跟踪代码也不容易发现这个错误,这样最终会为以后修复这个错误带来很大的困难。

@Override注解就是为了解决类似的问题,我们可以在子类重写父类的方法前加上@Override,表示这个方法是覆盖了父类的方法。如果该方法不是覆盖了父类的方法,例如将drive()写成了driver(),此时如果在driver()方法前加上@Override注解的话,则代码编译不会通过,将提示被@Override注解的方法必须在父类中存在同样的方法,程序才能编译通过。

需要补充一句,@Override注解只能用来修饰方法,不能用来修饰其他元素。

@Deprecated注解

如果读者之前使用Eclipse等集成开发环境编写过Java程序,会经常在属性或方法提示中看到@Deprecated。如果某个类成员的提示中出现了@Deprecated,就表示这个类成员已经过时,在未来的JDK版本中可能被删除,不建议使用。之所以现在还保留,是因为给那些已经使用了这些类成员的程序一个缓冲期,否则如果现在就删除这个类成员,那么这些程序就无法在新的环境下编译运行了。

在第8章介绍多线程的时候,我们会提到终止一个线程可以调用这个线程的stop()方法,但该方法已被废弃,不建议使用。通过查看JDK API,我们可以看到Thread类的stop()方法是被@Deprecated注解标注的,所以准确来说,这个stop()方法是因为过时而不建议使用。

简化前面Truck类的代码,并在drive()方法前使用@Deprecated注解标注。如果集成开发环境换成Eclipse,则在方法定义处、方法引用处及成员列表中都有变化,如图1.4所示。

这个例子中,Truck类的drive()方法被@Deprecated注解标注,提醒程序员这是一个过时的方法,尽量不要使用,避免以后出现问题。假设有个BigTruck类继承Truck类,并且重写了这个过时的drive()方法,又会怎样呢?编译程序,编译器会报错,提示“注意:BigTruck.java使用或覆盖了已过时的API。”和“注意:要了解详细信息,请使用-Xlint:deprecation重新编译。”

@SuppressWarnings注解

这个世界总是这么奇妙,既然有可以使编译器产生警告信息的注解,那么通常也会有抑制编译器产生警告信息的注解,@SuppressWarnings注解就是为了这样一个目的而存在的。先看看下面的代码。

编译程序,编译器会抛出警告信息“注意:TestZuChe.java使用了未经检查或不安全的操作。”和“注意:要了解详细信息,请使用Eclipse保存。”。显示结果如图1.5所示。

这个警告信息提示List类必须使用泛型才是安全的,才可以进行类型检查,现在未做检查,所以存在不安全因素。如果想取消这些警告信息,可使用如下代码。

再次编译程序,警告被抑制。当然,编译器发出警告,是要提醒程序员有哪些地方需要注意,抑制警告不是目的,正确的解决办法是使用泛型对集合中的元素进行约束,使对集合的操作可以被检查,如代码中被注释的部分那样。

@SuppressWarnings注解和前面两个注解不同之处在于,这个注解带一个参数,或者说有—个属性。注解@SuppressWarnings(value="unchecked")的含义为抑制不检查的警告。当然还可以同时抑制其他警告,例如@SuppressWarnings( value={"unchecked", "unused"})就同时抑制了不检查和未被使用的警告。下面列举了@SuppressWarnings注解相关属性值的含义。

• deprecation:使用了过时的程序元素。

• unchecked:执行了未检查的转换。

• unused:有程序元素未被使用。

• fallthrough:switch程序块直接通往下一种情况而没有break。

• path:在类路径中有不存在的路径。

• serial:在可序列化的类上缺少serialVersionUID定义。

• finally:任何finally子句不能正常完成。

• all:所有情况。

1.7.3 自定义注解

本节主要介绍自定义注解。不过要想让自定义注解真正起作用,必须要了解Java提供的4个元注解(用于修饰注解的注解):@Target、@Retention、@Documented和@Inherited。

注解之所以强大,能被众多框架所使用的主要原因在于,它可以允许程序员自定义注解,使Java程序变成自描述的。注解的语法形式和接口差不多,只是在interface前面多了“@”符号。

上面的代码是一个比较简单的注解,这个注解没有属性。我们可以在自定义注解时定义属性,在注解类型的定义中以无参方法的形式来声明,其方法名和返回值分别定义了该属性的名字和类型,其代码如下所示。

可以按如下格式使用MyAnnotation注解。

接下来修改自定义注解MyAnnotation,使其含两个属性,具体代码如下所示。

在注解中可以定义属性,也可以给属性赋默认值,具体代码如下所示。

定义了注解之后,接下来就可以在程序中使用注解,使用注解的代码如下所示。

请注意注释的描述,使用带属性的注解时,需要给属性赋值。不过如果在定义注解时给属性赋了默认值,则可使用不带属性值的注解,也就是让注解使用自己的默认值。

前文虽然讲解了自定义注解,但是肯定有不少读者觉得学完之后,心里空空的,不知道自定义注解到底有什么用?下面就来解决这个问题。

在自定义注解时,注解看起来和类、接口比较类似,尤其看起来更像接口。注解可以理解为和接口一样,是程序的一个基本组成部分。既然可以对类、接口、方法和属性等进行注解,那么当然也可以对注解进行注解。

使用不同注解对注解进行注解的方法,和对类、接口进行注解的方法一样,所不同的是,Java为注解单独提供了4种元注解,即@Target、@Retention、@Documented和@Inherited、下面分别介绍这4种元注解。

@Target注解

@Target元注解很容易理解,Target中文含义为目标,使用@Target注解的目的是用于指定被修饰的注解能用于修饰哪些程序元素。如果注解定义中不存在@Target元注解,则此注解可以用在任一程序元素上,如果存在这样的元注解,则编译器强制实施指定的使用限制。

此注解类型有唯一的value作为成员变量,其定义为public abstract ElementType[]value。接下来看这样的案例,将之前自定义的注解用@Target进行注解,以限制此注解只能使用在属性上。此时如果将此注解使用在方法上,编译器会报出“注释类型不适用于该类型的声明”的错误。案例具体代码如下所示。

@Target注解的属性value可以为如下值,被@Target注解的注解只能用来注解对应的目标。

• ElementType.ANNOTATION_TYPE:注解类型声明。

• ElementType.CONSTRUCTOR:构造方法声明。

• ElementType.FIELD:字段声明(包括枚举常量)。

• ElementType.LOCAL_VARIABLE:局部变量声明。

• ElementType.METHOD:方法声明。

• ElementType.PACKAGE:包声明。

• ElementType.PARAMETER:参数声明。

• ElementType.TYPE:类、接口(包括注解类型)或枚举声明。

@Retention注解

@Retention元注解用于指定被修饰的注解可以保留多长时间。如果注解定义中不存在@Retention元注解,则保留策略默认为RetentionPolicy.CLASS。

@Retention包含一个RetentionPolicy类型的value属性,使用此注解时必须为该value属性指定值。@Retention注解的value属性允许的值及含义整理如下。

• RetentionPolicy.CLASS:编译器把注解记录在class文件中,当运行Java程序时,虚拟机不再保留注解。

• RetentionPolicy.RUNTIME:编译器把注解记录在class文件中,当运行Java程序时,虚拟机保留注解,程序可以通过反射获取该注解。

• RetentionPolicy.SOURCE:编译器将直接丢弃被修饰的注解。

接下来通过一个案例,演示通过反射获取注解,具体代码如下。案例中提供了较为详细的注释。

代码中getObjectInfo()方法有两个注解,@MyAnnotation和@Deprecated,其中自定义注解@MyAnnotation的元注解@Retention的值为RetentionPolicy.RUNTIME,含义为当运行Java程序时,虚拟机保留注解,所以在运行时可以通过反射机制获取该注解。程序运行结果如图1.6所示。@Deprecated为内建注解,通过运行结果可以看出@Deprecated的元注解@Retention的值也是RetentionPolicy.RUNTIME。

@Documented注解

一看这个元注解的名字,就知道它和文档有关。默认的情况下使用javadoc工具自动生成文档时,注解将被忽略掉。如果想在文档中也包含注解,必须使用@Documented为文档注解。@Documented注解类型中没有成员变量。如果定义注解时使用了@Documented修饰,则所有使用该注解修饰的程序元素的API文档中都将包含该注解说明。

使用javadoc生成文档,产生的文档对TestAnnotation类的描述如下。

如果取消对@Documented的注释,使其起作用,将会出现另一个结果。

@Inherited注解

继承是面向对象的特性之一,Java是典型的面向对象语言,所以继承是Java的典型特性。前文讲过,注解是程序的一个基本组成部分,那么父类的注解是否被子类继承呢?默认情况下,父类的注解不被子类继承,如果要想继承父类注解,就必须使用@Inherited元注解。接下来通过下面的代码,介绍@Inherited注解的含义。

通过以上的代码,Truck类和Vehicle类一样都被MyAnnotation注解了。

1.8 变量和常量

1.8.1 变量

变量是一段有名字的连续存储空间(存储在计算机内存中)。在Java代码中通过定义变量来申请并命名这样的存储空间,并通过变量的名字来使用这段存储空间。通过给变量赋值可以改变变量的值,所以称之为变量。变量是程序中数据的临时存放场所,变量中可以存放字符串、数值、日期和对象等。

Java变量的核心要素是变量类型、变量名和变量值,其声明格式如下。

其中type表示Java的数据类型(1.9节会详细介绍Java的基本数据类型),其含义为这个变量里存的是什么类型的数据。varName是变量名,通过这个变量名使用这个变量。value是变量值,在声明变量的时候可以不初始化变量值。通过varName=newValue,可以给这个变量赋新的变量值。

对于内存而言,“type varName”是声明变量,相当于根据数据类型向内存申请一块空间,而“=value”相当于把变量值放到这个内存空间中。例如int stuAge=22(省略分号,以下同),可以拆分成int stuAge和stuAge=22两条语句,其中int stuAge相当于向内存申请一块可以存储int型变量的空间(实际为4字节,32位),而stuAge=22相当于把22放到了这块内存空间中。接下来还可以通过stuAge=27这条语句把27放到刚才的内存空间中,原来的22就不存在了。

在使用变量时,要避免出现未赋值就使用的情况。虽然在后面的章节中,会看到一些变量即使不赋值也会有默认值,但作为程序员,为了避免程序出错,也要做到变量先赋值后使用。

1.8.2 常量

在Java语言中,利用final关键字来定义Java常量,其本质为值不可变的变量。

因为Java常量的本质是值不可变的变量,所以在声明的时候,就必须要进行初始化。和变量不同的是,Java常量在程序中将无法再进行赋值,如果强行赋值,程序会抛出错误信息,并拒绝接受这一个新的值。例如,执行下面的程序(为了节省篇幅,代码中省去了部分注释)。

程序运行结果如图1.7所示。

1.9 Java数据类型

变量声明包括变量的数据类型和变量名,那什么是数据类型呢?什么是Java的数据类型和Java基本数据类型呢?

1.9.1 Java数据类型概述

假设编写程序让计算机完成这样的操作:一个学生的年龄是22岁,新年的钟声敲响之后,他的年龄就增加一岁,即为22+1。计算机如何执行这样的操作呢?首先,计算机要向内存申请一块空间,存放22这个数字,再申请一块空间,存放1这个数字,然后让计算机求这两个数字的和,存放到内存中。

学生的年龄是整数,现在申请了一块内存空间来存储,但如果要存储学生的姓名,或者存储学生的成绩(例如78.5),也是申请同样大小的一块内存空间吗?这样的内存空间能存下需要存储的数据吗?答案是否定的。

根据能对数据进行的操作以及数据所需内存大小的不同,把数据分成不同的类型。编程的时候,如果需要用到大数据,则需要申请大内存,这样就可以充分利用内存。

Java数据类型分为两大类,即基本数据类型和引用数据类型,如图1.8所示。其中引用数据类型又分为类、接口和数组,此部分内容在后面的章节会详细介绍。

Java基本数据类型分为4种,分别是整型、浮点型、字符型和布尔型。表1.1列出了不同的Java基本数据类型所占的字节数、位数和使用说明。

1.9.2 整型

Java各整型有固定的表示范围和字段长度,不受具体操作系统的影响,可以用来保证Java程序的可移植性。

Java整型常量有以下3种表示形式。

(1)十进制整数,例如12,-127,0。

(2)八进制整数,以0开头,例如014(对应于十进制的12)。

(3)十六进制整数,以0x或0X开头,例如0XC(对应于十进制的12)。

进制转换的内容不是本书涉及的范畴,如有不清楚的,请读者自行查阅相关资料。

Java的整型常量默认为int型,声明long型的整型常量需要在常量后面加上字母“l”或“L”,例如以下形式。

看下面的程序,其运行结果如图1.9所示。

程序运行出错的原因为,Java的整型常量默认为int型,其最大值为2 147 483 647,而在给maxNum赋值时,等号右边的整型常数为9999999999,大于int型的最大值,所以报错。处理方法是在9999999999后面加个“L”(或“1”)。

都是为了存整数,Java设计出4种整型类型的目的是存不同大小的数,这样可以节约存储空间,对于一些硬件内存小或者要求运行速度快的系统显得尤为重要。例如,需要存储一个两位整数,其数值范围在-99到99之间,程序员就可以使用byte类型进行存储,因为byte类型的取值范围为-128到127之间。

1.9.3 浮点型

在计算机系统的发展过程中,曾经提出过多种表示实数的方法,但是到目前为止使用比较广泛的是浮点表示法。相对于定点数而言,浮点数利用指数使小数点的位置可以根据需要而上下浮动,从而可以灵活地表达更大范围的实数。

Java浮点型常量有以下两种表示形式。

(1)十进制形式,例如3.14,314.0,.314。

(2)科学记数法形式,例如3.14e2,3.14E2,100E-2。

Java浮点型常量默认为double型,声明一个float型常量,则需要在常量后面加上“f”或“F”,例如以下形式。

不同于整型,通过简单的推算,程序员就可以知道这个类型的整数的取值范围。对于float和double,要想推算出来,需要理解浮点型的存储原理,且计算起来比较复杂。接下来,通过下面的程序,可以直接在控制台输出这两种类型的最小值和最大值,程序运行结果如图1.10所示。

1.9.4 字符型

字符型(char型)数据用来表示通常意义上的字符。

字符型常量为用单引号括起来的单个字符,因为Java使用Unicode编码,一个Unicode编码占2字节,一个汉字也是占2字节,所以Java中字符型变量可以存放一个汉字,例如以下2种形式。

Java字符型常量有以下3种表示形式。

(1)用英文单引号括起来的单个字符,例如'a''汉'。

(2)用英文单引号括起来的十六进制字符代码值来表示单个字符,其格式为'\uXXXX',其中u是约定的前缀(u是Unicode的第一个字母),而后面的XXXX是4位十六进制数,是该字符在Unicode字符集中的序号,例如'/u0061'。

(3)某些特殊的字符可以采用转义符'\'来表示,将其后面的字符转变为其他的含义,例如'\t'代表制表符,'\n'代表换行符,'\r'代表回车符等。

通过下面的程序及程序的运行结果(如图1.11),可以进一步了解Java字符的使用方法。

1.9.5 布尔型

Java中布尔型(boolean型)可以表示真或假,只允许取值true或false(不可以用0或非0的整数替代true和false,这点和C语言不同),例如以下形式。

boolean型在逻辑运算中一般用于程序流程控制,后面流程控制的章节经常会使用到此数据类型。

Java基本数据类型说明中,只有boolean型没有注明其占多少字节,有兴趣的可以自行研究一下。

1.9.6 基本数据类型转换

Java的数据类型转换分为3种:基本数据类型转换、字符串与其他数据类型转换以及其他实用数据类型转换。本节介绍Java基本数据类型转换,其中boolean型不可以和其他数据类型互相转换。整型、字符型、浮点型的数据在混合运算中相互转换遵循以下原则。

• 容量小的类型自动转换成容量大的数据类型,如图1.12所示。

• byte、short、char之间不会互相转换,三者在计算时首先会转换为int类型。

• 容量大的数据类型转换成容量小的数据类型时,需要加上强制转换符,但这可能造成精度降低或溢出,使用时需要格外注意。

• 有多种类型的数据混合运算时,系统首先自动地转换成容量最大的数据类型,然后再进行计算。

注:实箭头表示无信息丢失的转换,虚箭头表示可能有精度损失的转换。

通过下面的程序及程序的运行结果(如图1.13),可以进一步加深对Java基本数据类型转换的认识。

1.10 成员变量和局部变量

根据变量声明位置的不同,可以将变量分为成员变量和局部变量。

成员变量是在类的内部、方法(含语句块)外部定义的变量,其作用域从变量定义位置起到类结束。而局部变量是在方法(含语句块)内部定义的变量(包括形参),其作用域从变量定义位置起到方法(含语句块)结束。对于Java而言,类的外面不能有变量的声明。

下面的程序演示了成员变量和局部变量的作用域,运行结果如图1.14所示。

再看下面的例子,运行结果如何呢?

程序运行结果如图1.15所示,通过这个例子可以看出,方法中的局部变量可以和方法外的成员变量同名,如本例中的varT变量。在使用的时候,如果在局部变量所在的方法体内,局部变量覆盖成员变量,输出的结果是局部变量的值;如果在局部变量所在的方法体外,不在局部变量的作用域内,输出的是成员变量的值。

另外还需要注意的是,在Java中声明的成员变量可以不赋初始值,有默认的初始值(基本数据类型默认初始值为0、0.0、'\u0000'和false),如果声明局部变量则必须赋初始值。

1.11 Java运算符

Java支持如下运算符。

• 算术运算符:+、-、*、/、%、++、--。

• 关系运算符:>、<、>=、<=、==、! =。

• 赋值运算符:=、+=、-=、*=、/=等。

• 逻辑运算符:!、&&、||等。

• 位运算符:~、&、|、^、>>、<<、>>>(无符号右移)。

1.11.1 算术运算符

从参与运算的项数分,可以将算术运算符分为以下3类。

(1)单目运算符:+(取正)、-(取负)、++(自增1)、--(自减1)。

(2)双目运算符:+、-、*、/、%(取余)。

(3)三目运算符:(表达式1)?(表达式2):(表达式3),当表达式1的结果为真时,整个运算的结果为表达式2,否则为表达式3,该运算符是Java中唯一的三目运算符,常被使用。

通过下面的例子,来重点学习++、--、%和三目运算符这4个算术运算符。

程序运行结果如图1.16所示,通过这个例子可以看出,++和--这两个运算符放在操作数前或后,决定着是先自增(或自减)再运算,还是先运算再自增(或自减)。

“瑞达系统”的主界面,其中第五项内容为“计算Java工程师月薪”,接下来单独完成这一模块的功能。

注:同“租车系统”一样,“瑞达系统”也是贯穿本书的一个案例——利用Java实现Java工程师薪资和工作情况统计的案例。

假设Java工程师的月薪按以下方式计算。

Java工程师月薪=月底薪+月实际绩效+月餐补-月保险

其符合以下原则。

• 月底薪为固定值。

• 月实际绩效=月绩效基数(月底薪×25%)×月工作完成分数(最小值为0,最大值为150)/100。

• 月餐补=月实际工作天数×15。

• 月保险为固定值。

计算Java工程师月薪时,用户输入月底薪、月工作完成分数(最小值为0,最大值为150)、月实际工作天数和月保险4个值后,即可以计算出Java工程师月薪。具体代码如下。

本程序需要从控制台获取输入,所以在程序的第一行加入了代码“import java.util.Scanner;”,引入Scanner工具类,通过该工具类从控制台获取输入。具体获取输入的代码,通过程序中的注释,很容易看明白。

程序的实际运动结果如图1.17所示。

1.11.2 逻辑运算符

关系运算符和赋值运算符比较简单,这里不展开介绍。需要注意的是,关系运算符“==”和赋值运算符“=”看起来比较类似,但含义完全不同,“==”用于判断两边是否相等,而“=”,是将右边的值赋给左边。

+=、-=等是扩展的赋值运算符,x+=y等价于x=x+y,程序员在实际的编程过程中,为了方便阅读,尽量不要使用这种扩展的赋值运算符。

接下来重点介绍逻辑运算符。在Java中有3种逻辑运算符,它们是逻辑非(用符号“!”表示)、逻辑与(用符号“&&”表示)和逻辑或(用符号“||”表示)。

逻辑非表示取反,其逻辑关系值表如表1.2所示。

逻辑与的运算规则:有一个运算数为假,其值为假,两个运算数都为真,其值为真。逻辑与的关系值表如表1.3所示。

逻辑或的运算规则:有一个运算数为真,其值为真,两个运算数都为假,其值为假。逻辑或的关系值表如表1.4所示。

逻辑运算符在后面流程控制的章节中会经常用到,这里不再赘述。

1.11.3 位运算符

在计算机中,所有的信息都是以二进制形式存储的,可以对整数的二进制位进行相关的操作,这就是位运算符。位运算符主要包括按位非(用符号“~”表示)、按位与(用符号“&”表示)、按位或(用符号“|”表示)、按位异或(用符号“^”表示)和移位运算符(用符号“<<”“>>”“>>>”表示)。

在企业面试Java工程师的时候,也常会问“&&”和“&”以及“||”和“|”的区别,通过下面的学习,可以清楚地理解逻辑运算符和位运算符的区别。

按位非表示按位取反,其关系值表如表1.5所示。

按位与是逐位逻辑与。按位与的关系值表如表1.6所示。

按位或是逐位逻辑或。按位或的关系值表如表1.7所示。

按位异或是当两个运算位不同时,结果为1,否则为0。按位异或的关系值表如表1.8所示。

阅读下面的程序,分析程序运行结果。

程序运行的结果如图1.18所示,其中程序最后一段演示了“用性能最好的方法计算出5×8的结果”,这也是企业面试中常问的问题。

1.12 Java表达式

1.12.1 Java表达式概述

表达式是符合一定语法规则的运算符和操作数的组合。下面列举了一些表达式,需要注意的是,单个操作数也是表达式。如以下4行,每行均是一个表达式。

表达式的值:对表达式中的操作数进行运算得到的结果。

表达式的类型:表达式的值的数据类型即为表达式的类型。

1.12.2 表达式的运算顺序

Java表达式按照运算符的优先级从高到低的顺序进行运算,优先级相同的运算符按照事先约定的结合方向进行运算。运算符的优先级和结合性如表1.9所示。需要注意的是,程序员在编写代码时,是不会去记运算符的优先级的,当不确定运算符的优先级时,程序员通常的做法就是对先运算的部分加上小括号,保证此运算优先执行。

下面的例子看起来很简单,但作为程序员,总是在不经意间犯下这样的错误。当程序运行结果和预期结果有差异时,往往不容易找出错误所在。

输入两组不同的值(苹果数和小朋友数),如图1.19和图1.20所示,其中第二组得到的并不是预期的结果。原因在于stuApple=appleNum/stuNum这条语句,首先运算的是appleNum/stuNum,之后再进行赋值运算。appleNum/stuNum这个表达式中的两个操作数都是int型的,其运算结果也是int型,所以出现了3除以6,得到int型0的情况,再将int型的0赋给double型的stuApple,结果显示为0.0。

任务实施

1.13 任务1 开发环境搭建

配置JDK

1.下载并安装JDK

要想编译、运行Java程序,首先要下载JDK。在下载时需要注意,针对不同的平台有不同版本的JDK,需要选择下载与安装平台匹配的JDK。

另外,JDK的使用也不是版本越新越好。在企业级的开发中,通常一个项目中的开发人员统一使用一个稳定版本的JDK,避免因为各版本JDK的差异带来问题。

JDK的安装过程很简单,根据安装界面提醒进行操作即可。

2.Java环境变量

因为不同版本的JDK在安装过程中,有些会自动配置一些环境变量,有些需要用户手动配置。表1.10列举出通常需要配置的环境变量,如果JDK安装过程中没有配置,请大家手动配置。

3.配置环境变量

接下来以配置JAVA_HOME为例,具体介绍如何配置环境变量。在Windows XP系统中,右键单击“我的电脑”,选择“属性”→“高级”→“环境变量”命令,或者在Windows 7、Windows 10系统中,右键单击“计算机”,选择“属性”→“高级系统设置”→“环境变量”命令,在“系统变量”中,新建JAVA_HOME环境变量,如图1.21所示。

其他的环境变量配置类似,不同的是PATH这个环境变量不是新建的,是选中该环境变量后进行编辑修改。

验证JDK是否安装成功

在控制台下输入java-version命令,出现图1.22所示的结果即表明JDK安装成功。

1.14 任务2 注解应用

1.14.1 子任务1 内建注解应用

目标:完成本章1.7.2节中的所有程序。

时间:30分钟。

工具:Eclipse。

1.14.2 子任务2 自定义注解与元注解应用

目标:完成本章1.7.3节中的所有程序。

时间:60分钟。

工具:Eclipse。

1.15 任务3 Java简易程序开发

1.15.1 子任务1 第一个Java程序

编辑、编译、运行Java程序

1.编辑Java程序

JDK中没有提供Java编辑器,需要使用者自己选择一个方便易用的编辑器或集成开发工具。作为初学者,可以使用记事本、UltraEdit、Eclipse作为Java编辑器,编写第1个Java程序。下面以记事本为例,使用它编写HelloWorld程序。

打开“记事本”,按照图1.23所示输入代码(注意大小写和程序缩进),完成后将其保存为HelloWorld.java文件(注意不要保存成HeIloWorld.java.txt文件)。

2.编译.java源文件

在控制台环境下,进入保存HelloWorld.java的目录,执行javac HelloWorld.java命令,对源文件进行编译。Java编译器会在当前目录下产生一个以.class为后缀的字节码文件。

3.运行.class文件

执行java HelloWorld(注意没有.class后缀)命令,会输出执行结果,如图1.24所示。

Java程序概述

Java源文件以java为扩展名。源文件的基本组成部分是类(Class),如本例中的HelloWorld类。

一个源文件中最多只能有一个public类,其他类的个数不限,如果源文件包含一个public类,则该源文件必须以public类名命名。

Java程序的执行入口是main()方法,它有固定的书写格式。

public static void main(String[] args){...}

Java严格区分大小写。

Java程序由一条条语句构成,每个语句以分号结束。

图1.23中编写的这个程序的作用是向控制台输出“HelloWorld!”。程序虽然非常简单,但其包括了一个Java程序的基本组成部分。以后编写Java程序,都是在这个基本组成部分上增加内容。下面是编写Java程序的基本步骤。

(1)编写程序结构。

程序的基本组成部分是类,这里命名为HelloWorld,因为前面有public(公共的)修饰,所以程序源文件的名称必须和类名一致。类名后面有一对大括号,所有属于这个类的代码都写在这对大括号里面。

(2)编写main方法。

一个程序运行起来需要有个入口,main()方法就是这个程序的入口,是这个程序运行的起始点。程序没有main()方法,Java虚拟机就不知道从哪里开始执行。需要注意的是,一个程序只能有一个main()方法,否则不知道从哪个main()方法开始运行!

编写main()方法时,按照上面的格式和内容书写即可,内容不能缺少,顺序也不能调整,具体的各个修饰符的作用,后面章节会详细介绍。main()方法后面也有一对大括号,Java代码写在这对大括号里,Java虚拟机从这对大括号里按顺序执行代码。

(3)编写执行代码。

System.out.println("*********")方法的作用很简单,就是向控制台输出*********,输出之后自动换行。前面已经说过,JDK包含了一些常用类库,提供了一些常用方法,这个方法就是java.lang.System类里提供的方法。如果程序员希望向控制台输出内容之后,不用自动换行,则使用方法System.out.print()。

Java注释

为什么要有注释呢?

假设一个程序员新进入一个项目组,接手一个已离职程序员未完成的软件模块功能,当他打开原程序员编写的代码时,其中的一个方法有上百行代码,但没有任何注释。这样造成的结果是,新程序员要花费很长的时间去理解原程序员的业务逻辑和思路,可能还会出现理解错误的情况。怎么解决这个问题呢?在一个规范化的软件开发项目组里,程序的编写是必须要有注释的,Java程序编写也不例外。

什么是注释?

Java程序中的注释就是为了方便阅读程序而写的一些说明性的文字。通过注释提高Java代码的可读性,使得Java程序条理清晰,易于理解。

通常在程序开头加入作者、时间、版本、要实现的功能等内容作为注释,方便后来的维护以及程序员的交流。

Java的注释有3种:单行注释、多行注释、文档注释。

下面介绍一下Java程序员编写注释的规范。

(1)注释要简单明了,例如:

(2)边写代码边注释,修改代码的同时修改相应的注释,以保证注释与代码的一致性。有些时候会出现修改了代码,但没有修改注释的情况,尤其是在使用javadoc产生Java文档时,程序已经进行了修改,但文档注释没修改,产生的Java文档还是原注释内容,引起错误。

(3)保持注释与其对应的代码相邻,即注释的就近原则,通常是放在该段代码的上方或者放在该行代码的右边(单行注释)。

(4)在必要的地方注释,注释量要适中。在实际的代码规范中,要求注释占程序代码的比例达到20%左右。

(5)全局变量要有较详细的注释,包括对其功能、取值范围、哪些方法存取它以及存取时的注意事项等说明。

(6)源文件头部要有必要的注释信息,包括文件名、版本号、作者、生成日期、模块功能描述(如具体功能、主要算法、内部各部分之间的关系、该文件与其他文件的关系等)和主要方法清单及本文件历史修改记录等。以下是源文件头部注释示例。

(7)方法的前面要有必要的注释信息,包括方法名称、功能描述、输入与输出、返回值说明和抛出异常等。以下是方法注释示例。

(8)文档注释标签语法。

• @author,对类的说明,标明开发该类模块的作者。

• @version,对类的说明,标明该类的版本。

• @see,对类、属性、方法的说明,即相关主题。

• @param,对方法的说明,对方法中某参数的说明。

• @return,对方法的说明,对方法返回值的说明。

• @exception,对方法的说明,对方法可能抛出的异常进行说明。

下面是第一个Java程序增加注释后的完整程序。

本章介绍的与注释相关的内容较为详细,对于初学者来说,可能理解起来有些困难。没有关系,随着对Java学习的逐渐深入,再回过头来理解就会更加容易。

常见Java集成开发环境

以下是常见的Java集成开发环境。

1.Eclipse

Eclipse是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。

2.MyEclipse

MyEclipse是一个十分优秀的用于开发JavaSE、JavaEE的Eclipse插件集合,MyEclipse的功能非常强大,支持也十分广泛,尤其是对各种开源产品的支持非常不错。

MyEclipse企业级工作平台(MyEclipse Enterprise Workbench,MyEclipse)是对Eclipse IDE的扩展,利用MyEclipse可以极大地提高连接数据库和JavaEE的开发、发布以及应用程序服务器的整合的工作效率。它是功能丰富的JavaEE集成开发环境,包括了完备的编码、调试、测试和发布功能,完整支持HTML、CSS、JavaScript、SQL、Struts和Hibernate等。

1.15.2 子任务2 工程师月薪计算

目标:

完成“瑞达系统”主菜单向子功能的跳转,即当用户输入一个数字以后,跳转到该子功能模块。例如,如果用户输入5,则跳转到计算Java工程师的月薪模块。

程序运行结果如图1.25所示。

实现思路:

(1)使用switch语句实现,没有实现的模块直接打印“本模块功能未实现”,已实现的模块(例如模块5),执行相关功能;

(2)在main函数开始处,需要定义在相关模块中使用到的变量。

时间:15分钟。

工具:Eclipse。

拓展训练

“瑞达系统”获取用户输入

目标:

修改“瑞达系统”,当用户输入某个数(非0)时,执行该模块的功能,执行完毕之后,继续输出主界面。当用户输入0,则退出程序。程序运行结果如图1.26所示。

时间:20分钟。

工具:Eclipse。

实现思路:参考图1.26对应程序的实现思路。

参考答案:

综合训练

1.Java字节码文件的后缀为( )。(选择一项)

A .docx

B .java

C .class

D 以上答案都不对

2.下列描述中说法正确的是( )。(选择一项)

A 机器语言执行速度最快

B 汇编语言执行速度最快

C 高级语言执行速度最快

D 机器语言、汇编语言和高级语言执行速度都一样

3.下列哪个注解不是Java内建注解( )。(选择一项)

A @Target

B @Override

C @Deprecated

D @SuppressWarnings

4.下列选项中,( )是Java中的关键字。(选择一项)

A name

B hello

C false

D good

5.Java中用于定义实数的类型有____和____,后者精度高于前者。

6.JDK 5有哪些主要新特性?

7.什么是Java的垃圾回收机制?

8.为什么Java能实现目标代码级的平台无关性?

9.请列出Java有哪几个内建注解,并描述每个内建注解的含义?

10.请列出Java有哪几个元注解,并描述每个元注解的含义?

11.请描述@SuppressWarnings注解的value属性有哪些属性值?

12.请描述@Target元注解的value属性有哪些属性值?

13.Java中有goto关键字吗?

14.请描述Java有哪些基本数据类型?

15.Java的字符型可以存一个汉字吗?

16.请说明final、finally、finalize的区别(需要结合后面的章节才能回答此问题)。

相关图书

Effective Java中文版(原书第3版)
Effective Java中文版(原书第3版)
Java核心技术速学版(第3版)
Java核心技术速学版(第3版)
Java编程动手学
Java编程动手学
Java研发自测入门与进阶
Java研发自测入门与进阶
Java开发坑点解析:从根因分析到最佳实践
Java开发坑点解析:从根因分析到最佳实践
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)

相关文章

相关课程