书名:Java编程动手学
ISBN:978-7-115-61739-2
本书由人民邮电出版社发行数字版。版权所有,侵权必究。
您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。
我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。
如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。
著 汪 建 汪 立
责任编辑 傅道坤
人民邮电出版社出版发行 北京市丰台区成寿寺路11号
邮编 100164 电子邮件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
读者服务热线:(010)81055410
反盗版热线:(010)81055315
这是一本讲解Java基本语法的书,全书始终从初学者的角度,用通俗易懂的语言和形象生动的例子来讲解Java基础知识,让读者能轻松快速掌握。
本书共分为12章,首先介绍Java语言的基本情况;然后介绍如何在Windows、Linux和macOS三种操作系统中安装Java和集成开发环境以及JShell交互式编程;接着讲解Java的一些常见概念和数据类型以及Java的八大类运算符、各种表达式和语句;之后介绍类和对象这两个核心概念,数组与集合的概念和使用,Java常用工具类,以及Java的异常处理、注解以及泛型机制;最后讲解Java的文件与I/O的相关操作以及Java多线程和网络编程。
本书适合Java入门人员、初级开发人员以及想巩固Java基础的人阅读,也可作为自学Java或者正在参加Java培训的人员的参考书。
汪建(笔名seaboat),拥有10年以上的软件开发经验,擅长Java、Python和C++等编程语言,从事各类业务系统、中间件、基础架构、人工智能系统等研发工作。目前负责一个人工智能团队,致力于开发各种人工智能能力并赋能到业务系统中。精研工程算法、人工智能算法、自然语言处理、计算机视觉、架构、分布式、高并发、大数据、搜索引擎等方面的技术。平时喜欢看书、运动、写作、编程、绘画。崇尚技术自由,思想开放。著有《图解 Java 并发编程》《图解数据结构与算法》《Tomcat内核设计剖析》。
个人博客:blog.csdn.net/wangyangzhizhou
个人公众号:远洋号
汪立,拥有多年的大型系统开发经验,对Java语言及生态有浓厚的兴趣,对Spring、Spring Boot、Spring MVC、Spring Cloud、MyBatis、Dubbo、ZooKeeper等有较深入的研究,熟悉常用消息中间件(RocketMQ、Kafka、Elasticsearch、Redis)的使用及原理。此外,对JVM和分布式技术也有一定的研究,并持续关注Java开源技术的发展。
感谢读者,您的阅读让本书更有价值。
感谢公司提供的平台让我得到了很多学习和成长的机会。
感谢人民邮电出版社的傅道坤编辑一直以来给我的帮助和机会,如果没有他帮我出版第一本书,也就不会有后续的作品。
感谢好兄弟汪立花费很多时间和精力跟我一起完成本书的编写和内容审核。
感谢一直默默支持我的家人,你们让我能专心写作,让我的世界拥有更多色彩。
在此,也希望我可爱的儿子和女儿能健康快乐地成长。
记得早在2017年,在我跟人民邮电出版社的傅道坤编辑合作完《Tomcat内核设计剖析》这本书后,他就邀请我写一本面向Java初学者的图书,书的定位是专门为无Java基础的人提供入门指导。当时我谢绝了邀请,一来我当时已经把大部分精力投入人工智能相关的学习和研究上,二来我一直觉得市面上Java入门书已经很多了,我不觉得在时间和精力都比较受限的情况下能写得比那几本经典的图书好,况且写入门级的教程对我自己而言没有什么太大的意义。其间我又陆续跟傅编辑合作出版了另外两本书,还有一本人工智能科普书也快完稿了。转眼到2021年,此时傅编辑又问我要不要考虑写一本面向Java初学者的书,这一次我欣然地接受了这个任务。回望这些年,我写的书都是面向中高级开发人员的,冥冥之中觉得现在是时候写一本入门书了。
Java从1995年正式发布第一个版本开始到现在已有近30年,经过几十年的发展,它已经成为互联网时代主要的开发语言之一。如今整个Java生态已经相当繁荣,开发者数量也达到千万级,可见其在开发领域的受欢迎程度。近些年Java始终保持着快速的发展趋势,整个Java社区非常活跃且大版本的发布保持着很高的频率。虽然Java不断受到其他编程语言的挑战,但仍然一直在编程语言排行榜中位居前三名,这也足以证明它的生命力之顽强。
最早Java诞生的本意是用于智能电器,然而没有在该领域取得太大的成功。后来由于互联网兴起,Java凭借跨平台和面向网络的特性突然火了起来,当然这其中有一个非常重要的原因就是代码开源。Java最初的设计理念是“编写一次,到处运行”(Write Once, Run Anywhere),也就是说不管是什么硬件、什么操作系统,只要安装了Java运行环境就可以运行已经编译好的Java程序,而且不必针对硬件和操作系统重新进行编译。如今Java主要应用于移动端和服务器端的开发,移动端主要是安卓,而服务器端则是企业的业务系统、中间件和大数据组件等。从应用范围和发展趋势来看,开发者学会使用Java是非常有必要的。
本书具备如下特点。
● 本书鼓励你一定要动手,跟着书中代码一个个字母敲起来!
● 本书的定位是对Java基本语法的讲解,始终从初学者的角度,用通俗易懂的语言和形象生动的例子来讲解Java基础知识。
● 本书秉承“talk is cheap, show me the code”的极客精神,全书给出了数百个代码示例,对于每个细小的知识点都提供相应的代码。
● 本书非常适合自学,每节都有“考考你”和“动手做一做”两项任务,只要读者积极思考并动手完成任务便能快速掌握相关知识点。
全书共分为12章,具体如下。
● 第1章,走进Java世界:介绍了Java语言的基本情况、Java的发展史、如何选择Java版本以及Java语言的特性,同时讲解了JVM、JRE和JDK三个容易混淆的概念之间的关系,还介绍了Java的执行机制,最后介绍了Java的应用领域。
● 第2章,开发环境:介绍了如何在Windows、Linux和macOS三种操作系统中安装Java,然后通过第一个Java程序让我们第一次接触Java代码,接着介绍如何安装IDEA编程开发环境,最后介绍了JShell工具的使用。
● 第3章,基础知识:介绍了Java语言的基础知识,包括注释、标识符、关键字、变量、常量、数据类型、整数类型、浮点类型、字符类型、布尔类型、隐式类型转换以及显式类型转换。
● 第4章,运算符:讲解了Java八大类运算符,包括算术运算符、关系运算符、自增自减运算符、逻辑运算符、位逻辑运算符、移位运算符、赋值运算符及其他运算符,同时也分析了运算符的优先级。
● 第5章,表达式与语句:介绍了Java的表达式、语句、语句块以及程序的执行顺序,然后详细介绍了if条件分支语句、switch条件分支语句、for循环语句、while循环语句、do-while循环语句和return语句。
● 第 6 章,类与对象(上):介绍了 Java 这门面向对象编程的类与对象这两部分核心内容,讲解了面向对象编程、Java类的组成、如何通过类来创建对象、Java的包、类的封装性、static关键字、null关键字、无名称对象、对象的克隆以及对象的序列化和反序列化等。
● 第7章,类与对象(下):讲解了类的继承、super关键字、final关键字、重写方法、重载方法、多态性、instanceof关键字、抽象类、接口、枚举以及内部类等。
● 第8章,数组与集合:首先介绍了数组概念,从一维数组到二维数组,再到三维及更高维的数组,Java的数组类以及如何进行数组复制操作,然后介绍了Java的集合,包括列表类、集合类、映射类、队列类、堆栈类以及集合工具类。
● 第9章,Java常用工具类:介绍了Java常用的类,包括字符串类、运行环境类、系统类、基本数据类型包装类、数学类、随机数类、扫描类、日期类以及正则表达式。
● 第10章,异常、注解与泛型:首先介绍了Java语言的异常处理机制,包括try-catch组合、try-multi-catch组合、try-catch-finally组合、throw关键字以及throws关键字,然后介绍了@Override、@Deprecated和@SuppressWarnings三个注解。最后介绍了Java的泛型,包括泛型方法、泛型类型和泛型接口。
● 第11章,文件与I/O:讲解了Java中的文件和I/O操作,文件方面包括File文件类实现文件和目录的创建、删除、重命名,获取文件属性以及遍历文件目录等,I/O方面包括输入输出类、文件和对象输入输出以及文件读写器。
● 第12章,多线程与网络编程:首先介绍了Java语言多线程编程,包括进程、线程、多线程机制、线程生命周期、线程的创建、线程的优先级、守护线程、线程的休眠以及synchronized关键字,然后介绍了网络编程基础知识,包括各种网络协议、套接字、通信编程以及广播通信等。
● 想快速入门Java编程的人士。
● 想自学Java编程的人士。
● 初级和中级程序开发人员。
● 在校学生或正在参加Java培训的人士。
● 想巩固Java基础的人士。
在交稿时,我仍在担心本书是否遗漏了某些知识点,内容是否翔实齐备,是否能让读者有更多收获,是否会因自己理解上的偏差而误导读者。由于写作水平和写作时间所限,本书中难免存在错漏,恳请读者指正。
读者可将意见及建议发送到邮箱wyzz8888@foxmail.com,本书相关的勘误也会发布到我的个人博客blog.csdn.net/wangyangzhizhou上。欢迎读者通过邮件或博客与我交流。
本书提供如下资源:
● 本书源代码;
● “考考你”与“动手做一做”答案;
● 本书思维导图;
● 异步社区7天VIP会员。
要获得以上资源,您可以扫描下方二维码,根据指引领取。
作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。
当您发现错误时,请登录异步社区(https://www.epubit.com/),按书名搜索,进入本书页面,点击“发表勘误”,输入勘误信息,点击“提交勘误”按钮即可(见下图)。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。
我们的联系邮箱是contact@epubit.com.cn。
如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。
如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。
如果您所在的学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。
如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。
“异步社区”(www.epubit.com)是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作者与读者在线交流互动,以及传统出版与数字出版的融合发展。
“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域30余年的发展与积淀。异步图书面向IT行业以及各行业使用IT技术的用户。
Java从1995年开始正式发布第一个版本到现在已有近30年,它是一门非常优秀的编程语言。Java 的整个生态相当繁荣,长期以来它一直占据着编程语言排行榜前三的位置,开发者数量也达千万级,可见其在编程开发领域中的受欢迎程度。
Java语言是一门面向对象的通用编程语言,它最初的设计理念是“编写一次,到处运行”(Write Once, Run Anywhere)。也就是说,不管是什么机器、什么操作系统,只要该机器安装了Java运行环境就可以运行已经编译好的Java程序,而且我们不必针对硬件和操作系统重新进行编译。为什么能达到这种效果呢?答案是Java虚拟机(Java Virtual Machine,JVM),它将底层硬件和操作系统的差异进行了屏蔽。Java运行环境其实就是一个能够运行Java操作指令的虚拟机,这种Java操作指令被我们称为Java字节码。Java图标如图1.1所示。
图1.1 Java图标
随着互联网的快速发展,Java得到了空前的发展。现在Java主要应用于Web服务开发,很多世界级的互联网公司都把Java作为系统开发的主要语言。
Java最早由詹姆斯·高斯林(James Gosling)创造,有些网友称其“高司令”,他是公认的“Java之父”。最初的Java版权属于SUN公司,但后来该公司被Oracle公司收购,所以现在Java在商业方面的运营主要由Oracle推动。
虽然商业付费会使开发者对Java的态度更加谨慎,但由于Java语言一直存在开源版本——OpenJDK,因此不必担心Java语言未来会受到许可限制的问题。Java语言规范的发展主要由一个名为Java Community Process(JCP)的全球性组织管理,有实力的公司都会参与Java技术标准规范的制定,包括Oracle、IBM、Intel、SAP、阿里巴巴等知名公司。
截至写作本书时,Java最新版本——Java 18已经正式发布,目前Java以半年一个新版本的节奏更新发布。
考考你
● Java诞生于哪一年?
● Java语言的设计理念是什么?
● “Java之父”是谁?
● Java的开源版本叫什么?
虽然最初Java是在1995年发布的,但它的前身可以追溯到1991年,当时高斯林和其他两位同事一起创建了一个名为Oak的编程语言,设计该语言的初衷是用于交互式电视的开发。为什么把该语言称为Oak呢?这是因为当时高斯林刚好看到了办公室外边的一棵橡树,于是便命名为橡树(Oak)。但可惜的是该项目失败了,而失败的原因竟是理念和想法太超前了,当时的环境无法让这棵小橡树长成参天大树。
后来随着互联网的崛起,Sun公司决定改造Oak项目并重新对外发布,然而在发布时却发现Oak商标已经被注册了,于是该项目被重新命名为Java,Java是一种来自印度尼西亚的咖啡。
1995年Java的测试版首先发布,直到1996年才正式发布稳定的1.0版本。2007年SUN公司开源了Java平台的所有代码,并且全世界的开发人员都可以对Java平台的源代码进行修改。举着“编写一次,到处运行”的大旗,乘着互联网盛行的顺风,而且对所有代码开源且承诺免费使用,让Java逐渐流行起来并一路高歌猛进地快速发展着。
下面我们通过表1.1来了解Java每个版本的发布时间,1995年首次发布了Beta测试版。从表中也可以看到版本名称的变化,从最开始的JDK到J2SE再到JavaSE。从Java 9开始每个大版本的发布都以半年为周期,这么快的迭代速度使得Oracle不再承诺对所有版本都长期支持,他们决定只对其中某些大版本进行长期支持,到写作本书时只有Java 8、Java 11以及Java 17是长期支持(Long Term Support,LTS)的。其中如果是商业用途的话,最新且可免费使用的版本是Java 8,对于个人开发者而言则可以免费使用所有Java版本。
表1.1 Java各版本
版本 |
发布时间 |
是否长期支持(LTS) |
---|---|---|
JDK Beta |
1995年5月 |
否 |
JDK 1.0 |
1996年1月 |
否 |
JDK 1.1 |
1997年2月 |
否 |
J2SE 1.2 |
1998年12月 |
否 |
J2SE 1.3 |
2000年3月 |
否 |
J2SE 1.4 |
2002年2月 |
否 |
J2SE 5.0 |
2004年9月 |
否 |
JavaSE 6 |
2006年12月 |
否 |
JavaSE 7 |
2011年7月 |
是 |
JavaSE 8(LTS) |
2014年3月 |
是 |
JavaSE 9 |
2017年9月 |
否 |
JavaSE 10 |
2018年3月 |
否 |
JavaSE 11(LTS) |
2018年9月 |
是 |
JavaSE 12 |
2019年3月 |
否 |
JavaSE 13 |
2019年9月 |
否 |
JavaSE 14 |
2020年3月 |
否 |
JavaSE 15 |
2020年9月 |
否 |
JavaSE 16 |
2021年3月 |
否 |
JavaSE 17(LTS) |
2021年9月 |
是 |
JavaSE 18 |
2022年3月 |
否 |
实际上编程语言也是一个江湖,江湖上有多达几百个派系,各个派系之间可能是合作关系也可能互相竞争。那么Java在几百种编程语言中究竟表现如何呢?我们来看TIOBE上给出的主流编程语言近几十年的排名表现,如图1.2所示。可以看到Java在1996年排名28,然后一直处于高速发展态势,在2001年进入前三位,并且在后面的发展中一直保持着前三的位置,甚至多次排名第一。
图1.2 近年编程语言排名
总体来说,Java作为一门优秀的编程语言,拥有着繁荣的生态,一直占据着编程语言排行榜的前三位。所以我们作为IT开发者,掌握Java是非常有必要的。
考考你
● Java的前身叫什么?
● Java的取名来自什么?
● 我所在公司的商业系统可以免费使用Oracle公司提供的Java 11版本吗?
● 出于学习目的可以免费使用Oracle公司的所有Java版本吗?
前面我们看到了Java有很多版本,而且还在快速地不断推出新版本。对于刚入门的新手来说估计会被这些版本搞得头大,从Java 1.0到Java 16,该使用哪个版本呢?
在回答这个问题之前我们先来看一个2020年Java开发者调查报告,根据图1.3可以很清楚地看到目前大多数人还是在使用Java 8和Java 11,使用其他版本的人非常少。Java 7及以下版本实在是太旧了,所以用的人很少,而Java 9、Java 10和Java 12不是长期支持版本,所以用的人也少。此外,Java 13、Java 14、Java 15、Java 16、Java 17和Java 18几乎没人使用。剩下的Java 8和Java 11由于提供了长期支持,因此用的人最多。Java 8使用者最多的原因主要还是它是最后一个可以免费商用的版本。
图1.3 Java各版本使用率
下面我们再说一下大家比较关注的收费问题,对于上述除Java 8以外的Java商用版本,Oracle公司都是收费的。那么,如果既想用Java新版本又不想花钱,该怎么办呢?答案是使用OpenJDK,它是完全开源免费的。
OpenJDK其实是一个多方共同参与开发维护的项目,包括Oracle、Red Hat、IBM、Azul、Apple、SAP等众多知名公司都参与其中。在主流的Linux操作系统中很多使用OpenJDK作为系统自带的Java运行环境,使用OpenJDK的人也越来越多。实际上谁都可以基于OpenJDK的源码进行开发并发布,除了我们熟知的Oracle公司外,还有很多其他的公司也有自己的Java发行版本,比如阿里巴巴的Dragonwell、AWS的Corretto以及Azul的Zulu等。
重新回到最开始的问题,作为初学者应选择哪个版本的Java呢?实际上如果仅是出于学习Java的目的,那么最简单的方法就是使用最新的版本,但这里作者对版本的选择是基于如下几点考虑的。
● 首先,我们将Java 7及以下版本排除,它们实在是太旧了,对Java很多新特性和新语法都不支持。
● 其次,我们要选择长期支持的版本,即Java 8和Java 11。
● 最后,由于我们单纯是出于学习Java的目的而非商用,同时考虑学习Java最新的特性和语法,因此选择Java 11版本作为本书的标准版本。
书中所讲解的一些新工具在Java 11环境中都是支持的,同时书中涉及的所有代码都能够在Java 11环境中成功运行。
考考你
● Java版本中最多人使用的是哪两个版本?
● 随便列举几个基于OpenJDK开发的Java发行版。
● 为何本书选择Java 11作为学习对象?
Java从一开始就被设计成一种可移植、安全、简单的编程语言,它能一直受到大家的欢迎说明它是一门非常优秀的编程语言。那么它具备哪些优秀的特性呢?如图 1.4 所示,下面我们将列出Java语言的十大特性,并且对每个特性一一进行讲解。
图1.4 Java语言特性
● 上手简单。对于新手来说,学习 Java 是一件相对容易的事,因为它的语法非常简单明了,而且它是一门纯面向对象的编程语言,而面向对象的思考方式与现实世界十分贴合。此外,从某种意义上来说,Java是由C/C++演变而来的,它吸收了 C++的优点并改进了一些不足的地方,比如摒弃了指针这个复杂且易出错的概念,而且提供了垃圾回收机制,大大地简化了内存的管理工作。最后,Java创造了繁荣的技术生态,除了官方提供了丰富的类库,大量的第三方开发工具包和开源项目也不断地加入整个生态中。
● 跨平台。Java的跨平台主要表现在它的可移植性,即只要是Java程序(字节码)就可以运行在任意操作系统上,包括Windows、Linux、macOS和Solaris等操作系统,只需要它们安装Java虚拟机。我们知道C/C++语言会将代码编译成与硬件或操作系统相关的指令,这样就无法做到跨平台,而Java却能实现“编写一次,到处运行”的跨平台效果。要实现跨平台就要为每种操作系统都开发一个Java虚拟机,比如Windows版JVM、Linux版JVM、macOS版JVM,这些JVM用C/C++或汇编语言编写。
● 面向对象。面向对象是Java语言的基础特征,在Java世界中一切皆为对象。不同于函数编程,面向对象是将万物抽象成类,并在类内部定义相关属性和方法。相关的概念包括类、对象、属性、方法、封装、继承、多态和抽象等。
● 动态性。Java 的动态性主要体现在三个方面:一是支持动态地加载类,我们可以根据需要在运行过程中的任意时刻对类进行加载;二是支持动态地调整类的方法和属性,可以在运行时修改类结构;三是支持动态编译类,在运行过程中能对某段Java源码进行编译并运行。
● 安全性。Java语言本身具备很高的安全性,它摒弃了C/C++中指针的概念,从而能有效避免非法的内存操作。使用Java开发的应用能有效防止病毒和非法操作,这得益于Java程序运行在Java虚拟机沙箱内,内部的安全管理器会提供默认的策略来保护系统,所有未经允许的有害系统的行为都将会被禁止。
● 分布式。之所以说Java具有分布式特性,是因为通过它能很方便地开发分布式应用,比如Java提供的远程方法调用(Remote Method Invocation,RMI)和企业级Java Bean(Enterprise Java Bean,EJB),通过它们可以实现跨网络的方法调用,而代码看起来就像和本地调用一样。RMI和EJB现在很少使用了,因为有很多新的远程方法调用框架能更好地实现分布式应用。
● 多线程。Java从语言级上提供了多线程机制,使得我们能并行执行多项任务。Java提供的多线程能很好地解决各种并发问题,而且提供了同步机制和并发组件。
● 编译&解释。Java是一种编译和解释混合的语言,我们不能简单将其归类到编译型语言或解释型语言。Java源码会先被编译成字节码(后缀为.class的文件),然后JVM来解释这些字节码指令并开始执行,甚至在执行过程中还可能会将频繁执行的指令继续编译成底层的机器指令。
● 高性能。Java具有非常高的执行性能,它比其他任何解释型语言的执行速度都快。虽然整体上Java的性能仍然比不上C/C++(纯编译型语言),但随着Java的性能不断地被优化,它的执行速度已经非常接近C/C++了。
● 健壮性。Java语言具有很强的健壮性,内存的管理交由JVM使得Java程序不容易出现内存泄漏而导致崩溃,以及Java将易出错的指针屏蔽掉同样减少了程序崩溃的可能性。在语言层面,Java提供了异常捕获机制,能在程序运行中处理各种异常和错误,提升了程序的健壮性。
考考你
● Java语言的十大特性是什么?
● Java是如何做到跨平台的呢?
● Java的动态性主要表现在哪三个方面?
● Java的执行速度是否比C/C++还快?
Java开发人员经常会遇到JVM、JRE和JDK这三个概念,对于初学者来说常常分不清这些概念,本节将给大家介绍这三个概念。
首先我们看JVM,这个概念大家应该比较熟悉了,前面也说过它是Java虚拟机(Java Virtual Machine)的缩写。JVM是整个Java平台中最核心的部分,说它是虚拟机是因为它并不是真正存在的物理机,而是运行在物理机上的模拟计算机运行的一个进程。简单地说,JVM就是执行Java代码编译后的字节码指令的环境,它是Java的基础。
JVM结构如图1.5所示,主要包含了如下三部分。
图1.5 JVM结构
● 类加载器:用于将.class文件加载到内存并完成解析工作。
● 字节码校验器:它会对类加载器所加载的字节码进行一些校验,以判断是否存在违反规则的操作。
● 执行引擎:负责执行由Java代码经编译后的字节码指令。
当我们打开Java下载页面时就会发现不同的操作系统对应不同的版本,实际上就是JVM需要根据不同的操作系统开发不同的版本。Java语言的跨平台特性就是依靠这个来实现的,在不同的操作系统上抽象一个虚拟机层,从而屏蔽底层硬件的差异,最终达到跨平台的效果。如图 1.6所示,Windows操作系统对应Windows版本的JVM,Linux操作系统对应Linux版本的JVM,其他操作系统类似。这样,同一套.class文件(字节码指令)就能在不同操作系统上运行了。
图1.6 JVM与系统
JRE是Java运行时环境(Java Runtime Environment)的缩写。JRE包含JVM和一些JVM运行时所需的Java核心类库,此外还包含一些命令工具,如图1.7所示。JRE是Java代码可以运行的最低要求,带着你编写完的Java代码和对应系统的JRE就可以在其他机器上运行了。需要注意的是,自Java 11开始不再提供官方的JRE,取而代之的是由用户根据需求自定义JRE。
图1.7 JRE结构
JDK是Java开发工具集(Java Development Kit)的缩写。JDK包含JRE和开发过程中可能用到的一些命令工具,如图1.8所示。JDK是Java语言的最大的集合,我们常说的Java一般指的就是JDK,它包含一整套完整的开发工具集和运行环境。常见的命令工具包括java、javac、jdb、jar、javadoc、javah、jconsole、javap、jps、jstat、jinfo、jhat、jmap、jstack、jdeps、native2ascii等,涵盖了编译、调试、管理、反汇编、文档生成、诊断分析、监控、编码转换等方面的工具和命令。
图1.8 JDK结构
最后我们借图1.9展示JVM、JRE和JDK三者的关系,底层是提供Java运行环境的JVM。中间层的JRE还提供了Java核心类库,供JVM在执行字节码指令时调用所需的类库。JDK相当于一个完整的Java平台,包含Java编程开发调试工具和JRE。
图1.9 JVM、JRE和JDK的关系
考考你
● JVM、JRE和JDK分别是什么的缩写?
● JVM的作用是执行Java代码编译后的字节码指令吗?
● 我的工作电脑是Windows操作系统,所以应下载什么版本的JDK?
● 如果我想开发Java程序,只需要下载JRE就行了吗?
● JVM、JRE和JDK三者的关系是什么?
用Java语言编写的程序是怎样被运行的呢?本节将为大家讲解Java的运行机制,在讲解之前我们需要先了解一下编译型语言和解释型语言。我们都知道计算机是一个0和1的世界,计算机运行时根据一串0和1组成的指令来执行操作。我们称这些二进制指令为机器语言,它们对人类是十分不友好的,因为我们根本无法直接使用0和1进行编程。那么该怎么办呢?答案就是制定人类能看懂的编程语言(我们称之为高级语言),然后引入一种翻译机制将高级语言翻译成计算机语言,最后由计算机执行,如图1.10所示。
图1.10 程序运行机制
根据翻译的方式可以分为编译和解释,这两种方式的差异就在于翻译的时间不同。
对于编译型语言,它需要一个专门的编译过程,将高级语言编译成机器语言二进制文件。比如将C++代码编译成.exe二进制文件,这个文件就是由机器语言构成的。程序编译后每次运行时都可以避免再次编译,直接就可以运行,执行效率高。
从高级语言到机器语言的实际编译过程如图1.11所示,高级语言先编译成汇编语言,汇编语言再进一步编译成机器语言,最后是计算机执行这些机器语言。举个例子,高级语言中“a = b”(即将变量b赋值给变量a),经过编译后变成汇编语言“mov a,b”,然后再一次编译成机器指令“1000100111011000”。
图1.11 编译型语言运行
而对于解释型语言来说,它不需要事先执行编译工作,它把翻译的工作推后了,每次运行程序时都需要翻译一遍。比如shell脚本语言就是解释型语言,当我们编写完代码后不需要编译就能直接在计算机上解释执行,实际上就是在运行时由一个解释器将其翻译成机器语言并执行,如图1.12所示。由于每次执行都要使用解释器将高级语言翻译成机器语言,因此解释性语言的执行效率会比较低。
图1.12 解释型语言运行
上述两种类型语言的优缺点可以从以下两个方面来讨论。
● 执行效率。编译型语言明显更胜一筹,它在执行前一次性将所有高级语言都翻译成机器语言并保存起来,而解释型语言由于每次执行都需要翻译,因此效率低。
● 跨平台性。解释型语言具有更好的跨平台性,只需要支持不同硬件和操作系统的解释器就能运行同一套高级语言代码。而编译型语言在运行前会先将高级语言编译成指定硬件和操作系统的机器指令并保存成二进制文件,如果想在其他操作系统中运行,则需要先重新编译成其他操作系统的机器指令并保存成二进制文件。
Java 语言属于解释型还是编译型呢?实际上它将两者进行了结合,属于既包含解释又包含编译的混合型语言。Java在编译时并非直接编译成机器语言(机器指令),而是编译为中间语言(Java字节码指令),然后由解释器(JVM)解析并执行。由于中间语言是相同的,而不同操作系统和硬件的机器语言却是不同的,因此必须根据操作系统和硬件来实现不同的解释器。通过图1.13可以很清晰看出Java语言的编译与解释过程。
图1.13 Java语言运行过程
假如我们编写了一个hello.java文件,经过编译后成为hello.class文件,该文件保存的就是Java字节码,然后由不同操作系统的JVM解释执行,如图1.14所示。
图1.14 Java语言运行示例
如果Java语言仅通过解释器解析执行则执行效率较低,为了能提高执行效率,Java引入了即时(Just-In-Time,JIT)编译技术。之所以叫“即时编译”,是因为是在执行的时候进行编译的,把原来的Java字节码编译成机器指令,而且将这些机器指令缓存起来下次直接由计算机执行,从而有效避免解释工作,如图1.15所示。需要注意的是,并非每条字节码都会被即时编译器编译缓存起来,毕竟缓存也是需要成本的,只有那些高频的热点代码才会被即时编译器编译并缓存。
图1.15 Java编译机制
考考你
● 高级语言需要翻译成什么语言,计算机才能执行?大概过程是怎样的?
● 根据编译方式,编程语言可以分成哪两种?
● 编译型语言和解释型语言的各自优缺点是什么?
● Java是什么类型的语言?说说它的编译和解释的过程。
● “Java编译器会根据不同的操作系统编译成不同的中间码”。这种说法正确吗?
● 为了提高执行效率,Java使用了什么技术进行优化?
● Java即时编译器会将所有字节码编译成机器码并缓存起来吗?
经过二十多年的发展,使用Java编写的应用已经遍布在我们身边了,全世界已经有超过几十亿个设备在运行着 Java。有些应用是我们能直接接触到的,而更多的是以后台的形式提供服务。比如我们使用的电脑桌面程序和手机应用直接为我们提供各种功能,而后台的服务器则使用Java程序处理成千上万人的访问请求,同时服务器还用Java处理每天超亿量级的数据。那么Java的主要应用领域有哪些呢?如图1.16所示,下面我们一起来了解一下。
图1.16 Java应用领域
● 服务器应用。包括电子商务、电信、金融、银行、保险等信息化程度高的行业都大量使用Java来编写服务器应用,为这些行业的发展提供技术上的支持。
● Web应用。国内很多大型网站都使用Java进行开发,全世界的网站中超过一半Web应用都是用Java编写的。Java为我们提供了大量的Web开发框架,如Spring、Struts和Hibernate之类,以简化开发者的工作。Java主要用于服务端开发,几乎不用于客户端(浏览器)开发。
● Android应用。现在全世界每10人中就有超过8人使用Android系统的手机,而Android手机上的应用就是使用Java语言开发的。需要注意的是,Android应用虽然使用Java语言进行开发,但并非运行在我们通常所说的Java虚拟机上,而是运行在谷歌公司自己开发的一种虚拟机上。谷歌公司在推出Android操作系统时为了吸引开发者到Android生态中,采取了一个取巧的行为,把目光瞄准了拥有大量开发者的Java生态。为此,谷歌公司提供了与Java编程语言一样的语法和API,使得在应用层的开发者能像编写Java程序一样编写Android应用,这样一来一下子就吸引了大量的Java开发者到Android生态中。
● 大数据。大数据领域自2010年以来一直高速发展,现在一定规模的公司几乎都需要建立自己的大数据系统。在该领域中Java一直都是主要的开发语言,特别是大数据技术的经典代表Hadoop就是用Java编写的,这就为Java在该领域中奠定了非常重要的基础。除此之外还有很多重要的大数据工具是用Java开发的,比如HBase、Elasticsearch、ZooKeeper和Cassandra等。
● 嵌入式。嵌入式系统是一种专门的计算机系统,从办公室门禁到信用卡上的微型芯片再到庞大的服务器系统,都属于嵌入式系统。我们身边就有大量嵌入式设备,包括SIM卡、冰箱、空调、洗衣机、微波炉、电视、电梯、路由器等。使用Java非常便于开发嵌入式系统,而且所开发的程序能小到几百KB的量级。
● 数据科学。数据科学近些年已经成为最火热的技术领域之一,它主要是研究如何使用数据科学模型来解决现实中的问题,涵盖了信息检索、机器学习、自然语言处理、数据分析等。在该领域中Java同样提供了各种强大的工具库,如MLlib、Mahout、Weka、CoreNLP和DL4J等,能够非常方便地完成数据模型搭建。
● JavaME应用。随着iOS系统和Android系统的流行,它们在全世界的市场份额加起来几乎达到了99%,不断蚕食着JavaME的市场。不过在支持基于内核的虚拟机(KVM)的手机和一些机顶盒还是使用JavaME开发应用,有一定的市场规模。
● 桌面应用。桌面应用并非是Java的强项,但是仍然有很多经典的桌面应用使用Java进行开发,比如面向开发者的Eclipse、IntelliJ和NetBeans等,此外还有风靡全球的游戏Minecraft也是使用Java进行开发的。虽然桌面程序并非Java的强项,不过使用它开发桌面程序还是非常方便的。
Java平台根据不同的领域分成了JavaCard、JavaSE、JavaEE以及JavaME四个版本,详细介绍如下。
● JavaCard(Java Platform,Card):该版本主要应用于智慧卡开发,使得智慧卡装置能以安全的方式来执行Java Applet(小型程序),广泛应用于SIM卡、提款卡上。
● JavaME(Java Platform,Micro Edition):被称为J2ME,它主要应用于在资源受限的环境中开发,包括各种消费型电子产品,如机顶盒、移动电话和PDA之类嵌入式消费电子设备。
● JavaSE(Java Platform,Standard Edition):被称为J2SE,是Java平台的标准版,提供的标准库可用于开发桌面程序、服务器应用以及嵌入式设备的应用程序等。
● JavaEE(Java Platform,Enterprise Edition):被称为J2EE,是Java平台的企业版,主要定位于分布式企业系统应用的开发和部署,可以很容易开发出可移植、健壮、可伸缩且安全的服务器应用。
考考你
● Java有哪8个应用领域?
● Java平台分成哪4个版本?分别定位于哪个方向的开发?
● “Java开发Web应用时主要用于客户端浏览器开发”。这种说法正确吗?
● 我们能用Java开发一个像QQ一样的桌面应用程序吗?
● Android手机中的各种App是用什么语言开发的?
为了能开发并运行Java程序,我们需要安装Java环境,一般情况我们都会安装Java开发工具包(Java Development Kit,JDK),因为JDK包含了Java语言所有工具及运行环境,能方便我们开发。目前Window、Linux和macOS三种操作系统都有较多人使用,下面我们将以这三种操作系统为例讲解安装的过程。
首先需要下载JDK。可以到Oracle官网进行下载。
1.进入官网后,点击上面的Products,在下拉菜单中选择Java。
2.在该页面往下拉,找到Java SE,点击Download Java now进入下一页面。
3.下拉选择JDK的不同版本进行下载,此处以JDK 11为例进行下载。如图2.1所示,我们选择Windows系统的JDK进行下载。Windows系统的安装方式有两种:上面的exe格式文件是JDK安装程序,下载后直接运行一步步安装JDK;下面的zip格式文件是JDK的文件压缩包,下载后解压到指定路径。这里我们选择下载对新手更友好的exe格式的文件。
图2.1 JDK下载页面
完成下载后我们开始安装JDK,安装步骤如下。
1.双击运行,然后点击“下一步”。
2.该界面会默认设置JDK的存放路径,若想放在其他地方可以点击“更改”进行更改,这里选择存放在D:\JAVA\JDK\jdk-11.0.16.1路径下,然后继续点击“下一步”,如图2.2所示。
图2.2 JDK安装页面
3.等安装完成后点击“关闭”。安装过程中涉及的路径最好都使用英文字符,中文路径可能会导致意想不到的问题。
4.在之前版本中,JDK安装后就会自动安装JRE,但是从JDK 11开始,JRE需要我们手动进行安装。先到C:\Windows\System32路径下找到cmd.exe应用程序,然后点击右键,选择“以管理员身份运行”。
5.接着输入“D:”,并按回车键切换到D盘,输入并执行命令cd D:\JAVA\JDK\jdk- 11.0.16.1,跳转到JDK安装路径下。最后输入并执行命令bin\jlink.exe --module-path jmods --add-modules java.desktop --output jre,如图2.3所示。
图2.3 JRE生成命令
6.执行完后可以看到JDK安装目录下已经生成了jre文件夹,如图2.4所示。这表明已经成功安装了JRE。
图2.4 JDK目录
至此,还差配置环境变量这一步便能完成整个安装步骤,配置环境变量的目的是让计算机能够找到JDK,从而在执行Java程序命令时找到对应的应用程序。
1.右键点击“此电脑”后选择“属性”,如图2.5所示。
图2.5 打开电脑属性
2.然后一直往下拉,找到并点击“高级系统设置”,如图2.6所示。
图2.6 打开高级系统设置
3.点击“环境变量”,如图2.7所示。
图2.7 打开环境变量
4.在弹出的窗口中下方的“系统变量”区域点击“新建”按钮,如图2.8所示。
图2.8 打开新建系统变量
5.在弹出的窗口中的“变量名”输入JAVA_HOME,然后在“变量值”输入JDK的安装路径,按照作者上面安装的路径即输入D:\JAVA\JDK\jdk-11.0.16.1,点击“确定”完成创建,如图2.9所示。
图2.9 新建JAVA_HOME系统变量
6.在“系统变量”中找到Path变量,选择后点击“编辑”,然后点击“新建”分别添加“%JAVA_HOME%\bin”和“%JAVA_HOME%\jre\bin”两个变量值,其中“%JAVA_HOME%”代指前面创建的“JAVA_HOME”变量所存放的路径,如图2.10所示。
图2.10 添加Path系统变量值
7.在“系统变量”继续点击“新建”按钮,在弹出窗口的“变量名”输入CLASSPATH,“变量值”输入“%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar”,然后点击“确定”按钮,如图2.11所示。至此,环境变量配置完成。
图2.11 新建CLASSPATH系统变量
完成上述所有安装和配置步骤后,就可以开始验证安装是否成功了。在cmd窗口中输入java -version,执行后能看到JDK的版本,如图2.12所示,说明我们已经成功安装配置好JDK,至此我们已经向Java编程踏出了第一步。
此处前面的java命令其实就是执行Path变量的变量值“%JAVA_ HOME%\bin”(即“D:\JAVA\JDK\jdk1.8.0_301\bin”)路径下的java.exe应用程序,-version是执行该应用程序时所指定的参数。
图2.12 验证JDK安装配置
同样地,首先要到Oracle官网下载JDK,直接找到Linux系统的JDK进行下载。根据自己的系统及架构选择安装包,此处作者的系统是x86架构,且为了选择一种通用的安装方式,因此选择下载x86架构的通用压缩包。当然使用Red Hat或Debian的Linux系统时可以直接下载对应的安装包进行更便捷的安装。
下载好压缩包后我们先新建一个存放JDK的目录,执行命令sudo mkdir/usr/local/java,如图2.13所示。其中sudo表示使用管理员权限,第一次执行命令时需要输入用户密码,mkdir是创建目录命令,/usr/local/java是所创建的目录。
图2.13 Linux下载JDK
然后把压缩包解压到新建的目录下,执行命令sudo tar -zxvf ~/下载/jdk-11.0.11_linux-x64_ bin.tar.gz -C /usr/local/java,如图2.14所示,解压完成后便完成了JDK的安装。其中tar是解压命令,-zxvf是解压命令的参数,“~/下载”是刚刚下载JDK压缩包的默认下载路径(~表示用户根目录),jdk-11.0.11_linux-x64_bin.tar.gz是刚刚所下载的JDK压缩包,-C是指解压到指定目录下,/usr/local/java是解压目录。
图2.14 JDK安装
接着还需要配置环境变量,执行命令sudo vi ~/.bashrc编辑用户目录下的.bashrc文件。在该文件末尾处添加代码清单2.1中的内容,其中JAVA_HOME右边的内容是刚刚JDK的安装路径,等号右边若存在多个变量值则使用冒号隔开。此外$符号表示获取对应变量的值,比如$JAVA_HOME表示变量JAVA_HOME的值。而export则表示把变量设置为环境变量。
代码清单2.1 配置Linux环境变量
1. # set JDK environment
2. export JAVA_HOME=/usr/local/java/jdk-11.0.11
3. export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
4. export PATH=$JAVA_HOME/bin:$PATH
最后执行命令source ~/.bashrc使刚刚配置的变量生效。再执行命令java -version,如果可以看到JDK的版本信息,如图2.15所示,则说明安装成功了。
图2.15 验证Linux的JDK安装
首先到Oracle官网下载macOS安装包。macOS系统的安装方式有两种,如图2.16所示。上面的dmg格式文件是JDK安装程序,下载后打开能一步步安装JDK。下面的gz格式文件是JDK的文件压缩包。我们选择下载dmg格式的文件。
图2.16 下载macOS的JDK安装包
下载完成后找到刚刚下载的JDK安装包,双击运行。
双击运行后会弹出窗口,我们继续双击pkg文件。
然后就能看到JDK的安装界面了,我们点击“继续”。
进入下一界面后,我们能看到JDK所占用的空间,接着点击“安装”。
安装完成后就可以看到安装成功的界面,接着点击“关闭”来关闭安装界面。
接着是配置环境变量,首先查看一下我们的JDK安装到了哪里。打开终端,然后输入/usr/libexec/java_home -V,我们就能看到JDK的安装路径,如图2.17所示。
图2.17 查询JDK安装路径
输入命令cd ~/确保我们是在home目录下,然后输入命令ls -a查看当前路径下是否存在.bash_profile文件。
若不存在.bash_profile文件,我们就输入命令touch .bash_profile来创建该文件。
然后输入命令open -e .bash_profile打开并编辑该文件,添加的内容如图2.18所示。
图2.18 配置macOS环境变量
编辑完成.bash_profile文件后,输入命令source .bash_profile来激活配置以使该文件内的配置生效。
至此已完成整个安装和配置,我们输入命令java -version来验证是否安装成功,如果能查看JDK的版本就说明安装成功了,如图2.19所示。
图2.19 验证macOS的JDK安装
动手做一做
根据本节的安装步骤在你的系统中成功安装Java环境。
在我们成功安装JDK环境后就可以开始开发Java程序了。由于我们还没正式学习Java相关的基础知识和语法,这里仅编写一个最简单的Java程序,目的在于让大家了解Java程序的开发过程以及看到机器输出“Hello Java!”。
Java程序的编写及运行的步骤如图2.20所示。
1.创建一个xxx.java文件,后缀为.java的文件是源代码文件。
2.用记事本打开xxx.java文件并编写代码。
3.使用编译器(javac)将xxx.java文件编译成xxx.class文件,执行命令为javac xxx.java。
4.执行java xxx命令便能执行我们编写的程序,该命令实际上就是调用JVM来执行xxx.class文件中的字节码。
图2.20 Java编程步骤
第一个Java程序的编写及运行的步骤如下。
1.在某个目录下创建一个HelloJava.java文件,比如在D:\myProject目录下。
2.用记事本打开HelloJava.java文件并编写代码。
在该文件中输入图2.21的内容,注意对代码中的换行和缩进并没有严格的要求,它们的功能就是对代码进行排版,使代码结构更清晰。两个记事本中的HelloJava.java文件的缩进和换行都是允许的,很明显上面那种更加清晰明了。
图2.21 不同的代码格式
3.通过按Windows微标+R组合键打开“运行”界面后输入cmd并按回车键调出命令窗口,然后输入“d:”并按回车键切换到D盘,继续输入命令cd myProject并按回车键进入myProject目录,最后执行javac HelloJava.java命令,该命令会对HelloJava.java源文件进行编译并生成HelloJava.class文件,该文件就是JVM执行时所需的字节码文件,如图2.22所示。
图2.22 编译源文件
4.在命令窗口中执行java HelloJava命令并按回车键便能执行我们编写的程序了,该命令实际上就是调用JVM来执行HelloJava.class文件中的字节码,最终我们看到机器输出“Hello Java!”,如图2.23所示。
图2.23 执行字节码
虽然我们按照步骤让机器输出了“Hello Java!”,但是大家肯定会有很多疑惑。代码中的public是什么?class、static、void、main、String[] args、System.out.println()等又是什么?大括号有什么作用呢?下面将简要解答以上的问题,从而使大家能初步了解Java的基本知识和概念,我们通过图2.24来说明。
图2.24 了解代码
● public:属于Java语言的关键字,用于表示可见性的访问修饰符,可修饰类、接口、方法和变量,表示所有类都可以访问它。
● class:属于Java语言的关键字,用于声明这是一个类。
● HelloJava:自定义的类名称。
● static:属于Java语言的关键字,声明方法或属性为静态,对于被它修饰的方法和属性,可以在不创建对象的情况下访问它们。
● void:属于Java语言的关键字,表示该方法返回值为空,即不返回任何值。
● main:它是Java非常特殊的一个方法,是程序开始的地方。
● String[] args:表示Java程序运行时命令行传入的参数。
● System.out.println():表示调用System类中的out对象的println方法,该方法能将信息输出到屏幕上,待输出信息放到括号中。
● 大括号:Java中的大括号都是成对出现的,它的作用主要是使代码结构更清晰、简洁、易懂,同时,一对大括号也指定了代码的作用域。
考考你
● 编写运行Java程序的4个步骤是什么?
● Java代码中的换行和缩进是否有严格要求?不按要求将导致程序出错吗?
● 如何打开命令窗口?
● 编译Java源码的命令是“javac xxx.java”吗?
● 运行编译后字节码文件的命令是“java xxx.class”吗?
动手做一做
编写运行自己的第一个Java程序,类名称为MyFirstJava,功能是输出“My first Java!”。
我们在2.2节中直接使用记事本来编写代码,这其实是一种原始且低效的方式,而如今基本都是使用集成开发环境(IDE)来编写代码,IDE提供了各种各样的专业工具来提高编码效率。很多厂商都为Java专门提供了IDE,其中IDEA是最受欢迎的一款,下面我们以Windows系统为例来看看如何安装IDEA。
先到JetBrains官网下载IDEA的安装包。进入后点击Developer Tools,然后点击IntelliJ IDEA。
在下一页面中,有两个Download按钮,点击其中任意一个进入下载页面。
在下载页面有Ultimate(旗舰版)和Community(社区版)两种版本,前者多用于企业开发,个人使用则选择后者进行下载即可。点击Download默认下载最新版本,若想下载其他版本可以点击左侧的Other versions进行版本选择。
下载完成后运行安装包,在弹出页面点击Next。
在下一页面里,可以使用默认安装路径,也可以点击Browse自己选择安装路径。配置好安装路径后点击Next。
勾选64-bit launcher则会在桌面创建一个64位的快捷方式。然后点击Next,如图2.25所示。
图2.25 IDEA安装
继续点击Install,开始进行安装,安装完成后点击Finish。
同样地,在安装完成IDEA后我们学习如何通过IDEA编写并运行第一个Java程序,步骤如下。
1.双击进入IDEA,接下来点击File→New→Project来创建第一个项目,如图2.26所示。
图2.26 创建项目
2.左边选择Java,SDK会自动扫描使用JDK,如图2.27所示,然后点击Next。
图2.27 指定项目JDK
3.下一页面中不勾选Create project from template,然后点击Next。
4.输入项目名和项目存放路径,如图2.28所示,然后点击Finish,如果存放路径不存在,会弹出一个Directory Does Not Exist的窗口,提示将会创建路径,点击Create即可。
图2.28 新建项目2
5.新建完成后就可以在左边栏看到我们的项目了,如图2.29所示。
图2.29 项目展示
6.接下来创建包,右键点击src文件夹,然后点击New→Package,会弹出输入包名的小窗口,直接输入包名,然后按回车键就创建好了。
7.接着创建类,右键点击刚刚新建的包,然后点击New→Java Class。
8.弹出新建窗口,我们输入类名,选择Class类型,如图2.30所示,然后按回车键即创建完成。
图2.30 创建类
9.在HelloJava的类内输入代码清单2.2的内容,按Ctrl + S组合键保存文件,如图2.31所示。
代码清单2.2 创建HelloJava
1. public static void main(String[] args) {
2. System.out.println("Hello Java!");
3. }
图2.31 IDEA编辑类
10.在文件编辑区点击右键→Run来执行代码,至此我们就成功地在IDEA运行第一段代码了。
接着我们来了解一下IDEA的版面,如图2.32所示,它主要分为三个大的区域,左边是项目结构目录,右边是文件编辑区,下面是代码运行区。代码运行区中可以查看代码输出结果,也包括运行相关的一些按钮。
图2.32 IDEA版面
版面菜单栏各菜单的主要功能如下。
● 文件(File)菜单:主要用于对文件进行操作,包括新建、打开、导出、打印等,且能对IDEA进行设置等。
● 编辑(Edit)菜单:主要用于对文件内容进行操作,包括复制、粘贴、剪切、查找等。
● 视图(View)菜单:该菜单是对各个界面进行设置、操作,界面包括工具栏、状态栏、导航栏等。
● 导航(Navigate)菜单:用于快速定位到资源处,比如查找指定类、文件、父方法,定位到指定行等。
● 代码(Code)菜单:用于对代码进行操作,比如把整行代码上移或下移、构造通用代码、快捷注释代码等。还要记住该菜单的几个常用快捷键,可提高编写代码时的效率。
● 分析(Analyze)菜单:用于对代码进行分析、检查等操作。
● 重构(Refactor)菜单:用于对资源进行重构操作,比如对类名、变量名等进行重构操作后,所有使用了该资源的地方都会全部一起更改,避免人工逐个查找修改。
● 构建(Build)菜单:用于构建项目。
● 运行(Run)菜单:用于运行代码相关操作,比如运行、测试等。
● 工具(Tools)菜单:用于把文件、项目保存为模板等。
● 版本(VCS)菜单:用于版本控制相关操作。
● 窗体(Window)菜单:用于对各个窗体进行相关操作。
● 帮助(Help)菜单:用于查看IDEA使用手册、注册、更新、反馈等。
对于初学者来说,有一个非常有用的工具可以帮助学习Java,这个工具就是Java Shell(JShell)。JShell是在Java 9中引入的,提供了一种“读入-求值-输出”循环(Read-Eval-Print Loop,REPL)交互式编程环境,如图2.33所示。
图2.33 JShell
常规情况下我们使用经典的“编辑-编译-运行-调试”模式进行程序开发,但对于探索性的编程和某些调试工作,REPL模式却更加便捷高效。初学Java,有许多内容是需要快速探索并得到答案的,所以我们必须学会使用JShell。通过JShell可以省却“类定义”和“public static void main(String[] args)方法”,从而快速学习Java语法和API、验证逻辑运算以及调试等。
REPL模式的核心就在于不断循环“读入-求值-输出”过程,读入就是读取一个来自用户的表达式,比如“var a=1+2+3”。求值就是求出读取的表达式的值,前面例子求值后为“a=6”。输出就是将求值结果展示给用户,前面例子将在屏幕上显示“a ==> 6”。
为什么这么强调使用JShell呢?通过前面的学习我们已经知道了Java程序开发的大致步骤如下。
1.创建一个后缀为.java的文件,比如HelloJava.java。
2.在HelloJava.java文件中编写程序。
3.使用编译器(javac)将HelloJava.java文件编译成HelloJava.class文件,如果使用了IDEA则这一步会自动执行。
4.执行java HelloJava命令便能执行我们编写的程序,该命令实际上就是调用JVM来执行HelloJava.class文件中的字节码。
5.如果程序运行结果错误或逻辑有问题,则需要我们找出问题并修复错误,该阶段涉及修改HelloJava.java文件。
6.重复上述第2步~第5步,直至我们觉得程序没问题。
这就是典型的“编辑-编译-运行-调试”模式,这个过程可以通过REPL模式进行优化,它能快速验证程序运行结果和逻辑,在验证结果后我们再用验证过的代码编写Java源文件,或者不必再编写Java源文件,因为我们需要的仅仅只是运行结果。
考考你
● Java从哪个版本开始引入JShell?
● REPL是什么?
● REPL模式与“编辑-编译-运行-调试”模式相比有什么优势?
说了这么多,赶紧看看如何使用JShell吧。首先启动JShell运行环境,直接打开命令窗口,然后输入jshell就能进入JShell运行环境,如图2.34所示。
图2.34 进入JShell
对于Windows系统,按Windows徽标+R组合键,在左下角弹出的小窗口中输入cmd后按回车键,命令窗口就弹出来了。对于Ubuntu系统,按Ctrl+Alt+T组合键即可打开命令窗口。对于macOS系统,按Command键+空格键,输入terminal即可找到。
接着输入“var a=1+2+3”,系统会自动返回“a ==> 6”,告知你a变量等于6,你也可以输入a查看a变量,或者输入System.out.println(a)查看变量a的值,如图2.35所示。
图2.35 执行JShell
当我们使用JShell后准备退出JShell运行环境时,只需输入/exit,如图2.36所示。
图2.36 退出JShell
JShell让我们可以用交互的形式来快速执行代码片段并得到结果,其中代码片段可以是语句、变量、方法、类定义或表达式等。
JShell中可以通过声明语句来定义一个变量,如代码清单2.3所示,输入“int x = 10;”后按回车键便完成了变量x的创建,字符串类型变量的创建也类似。
代码清单2.3 定义变量
1. jshell> int x = 10;
2. x ==> 10
3. | 已创建 变量 x : int
4.
5. jshell> String s = "haha";
6. s ==> "haha"
7. | 已创建 变量 s : String
在JShell中执行表达式后会得到一个值,如代码清单2.4所示,比如执行“3+4”会得到一个为7的值,并且自动创建一个临时变量来保存它,例子中当前的临时变量名为$13,注意暂存变量名会不断改变。当我们输入$13时JShell将输出它的值和数据类型。当然也可以将表达式的结果赋值给指定的变量,比如执行“int b = 3 + 4;”会将结果赋值给变量b,当我们输入b时会输出它的值和数据类型。
代码清单2.4 执行表达式
1. jshell> 3 + 4
2. $13 ==> 7
3. | 已创建暂存变量 $13 : int
4.
5. jshell> $13
6. $13 ==> 7
7. | $13 的值: int
8.
9. jshell> int b = 3 + 4;
10. b ==> 7
11. | 已创建 变量 b : int
12.
13. jshell> b
14. b ==> 7
15. | b 的值: int
也可以在JShell中定义方法,如代码清单2.5所示。由于方法一般有多行代码,因此在编写完一行代码并按回车键后会进入下一行的编写,此时当前行提示符不再是jshell>,而是“...>”,直到完整的方法编辑完成后按回车键。下面例子展示了方法的创建,创建完成后可以直接调用该方法。
代码清单2.5 创建方法
1. jshell> void printInfo(String info){
2. ...> System.out.println("input info : " + info);
3. ...> }
4. | 已创建 方法 printInfo(String)
5.
6. jshell> printInfo("hello world");
7. input info : hello world
假如某个变量、方法或类在前面已经定义过了,那么如果想要覆盖它们则可以通过重定义来实现。所谓重定义就是重新定义一个与之前元素名称相同的元素,从而覆盖原来的定义。如代码清单2.6所示,JShell会提示“更新已覆盖”。对于方法和类的重定义也是一样的。
代码清单2.6 变量重定义
1. jshell> int aa = 10;
2. aa ==> 10
3. | 已创建 变量 aa : int
4.
5. jshell> int aa = 20;
6. aa ==> 20
7. | 已修改 变量 aa : int
8. | 更新已覆盖 变量 aa : int
9.
10. jshell> String aa = "haha";
11. aa ==> "haha"
12. | 已替换 变量 aa : String
13. | 更新已覆盖 变量 aa : int
当执行的代码片段有错误时JShell会抛出异常,如代码清单2.7所示,比如我们定义了一个除法方法,当我们传入的除数为0时会抛出“java.lang.ArithmeticException:/ by zero”异常。
代码清单2.7 抛出异常
1. jshell> int divide(int x, int y){
2. ...> return x/y;
3. ...> }
4. | 已创建 方法 divide(int,int)
5.
6. jshell> divide(6,0);
7. | 异常错误 java.lang.ArithmeticException:/ by zero
8. | at divide (#2:2)
9. | at (#3:1)
最后我们要注意,每次打开JShell都是独立的,在之前打开的JShell中定义过的变量、方法、类都不会被保存,它们都只是临时性的,当JShell关闭时将被全部清除,所以JShell只适合临时实验性编程。
考考你
● JShell中可执行的代码片段包括哪些?
● 如何对变量进行重定义?
● 什么情况下会产生临时变量?
动手做一做
打开命令窗口并成功进入JShell环境,然后将本节所有示例的代码都执行一遍,观察结果是否与书中的相同。
JShell也有自己的命令,这些命令用于执行特殊操作或展示信息,所有命令都以斜杠(/)开始,以便与代码片段区分开。
我们可以通过命令“/vars”来查看所有定义过的变量或隐藏变量,如代码清单2.8所示。假设我们定义了a、b、c三个变量并自动生成了一个隐藏变量,那么通过“/vars”命令就能得到如下的结果。
代码清单2.8 查看所有变量
1. jshell> /vars
2. | int a = 10
3. | int b = 20
4. | int c = 30
5. | int $4 = 40
如果想要查看所有定义过的方法则可以使用/methods命令进行查看,如代码清单2.9所示。假设我们定义了test()、test2()和test3()三个方法,通过/methods命令查询出的结果如下。
代码清单2.9 查看所有方法
1. jshell> /methods
2. | String test()
3. | void test2(String)
4. | int test3()
对于定义过的类可以通过/types命令来查看,如代码清单2.10所示。假设我们定义了A、B、C三个类,那么通过/types命令查询出的结果如下。
代码清单2.10 查看所有类
1. jshell> /types
2. | class A
3. | class B
4. | class C
当我们想查看已经执行过哪些代码片段时可以通过/list命令来查看,如代码清单2.11所示。它可以按顺序将执行过的代码片段都打印出来,比如下面一共执行了4个代码片段。
代码清单2.11 查看执行过的代码片段
1. jshell> /list
2. 1 : int a = 10;
3. 2 : class A{
4. int x;
5. int y;
6. }
7. 3 : System.out.println("haha");
8. 4 : 20+40
想要退出JShell可以使用/exit命令,如代码清单2.12所示。退出后会回到原来命令窗口。
代码清单2.12 退出JShell
1. jshell> /exit
2. | 再见
3.
4. C:\Users\seaboat>
还有其他一些不太常用的命令,可以通过/help命令来查看帮助文档。
考考你
JShell命令以什么符号开始?
动手做一做
在JShell中输入本节学习的所有命令。