Java程序设计入门(第2版)

978-7-115-53157-5
作者: [印度]沙姆▪蒂克库(Sham Tickoo)
译者: 郭奇青
编辑: 陈聪聪龚昕岳
分类: Java

图书目录:

详情

本书是关于Java语言程序设计的入门图书。全书从Java入门开始,介绍了Java基础,控制语句与数组,类与对象,继承,包、接口和内部类,异常处理,多线程,字符串处理,Applet与事件处理,抽象窗口工具包,Java I/O系统等内容。通过本书的学习,读者可以从零开始认识和掌握Java语言的基本概念和数据结构。 本书不但适用于Java语言的初学者,而且可以作为大专院校相关专业师生的学习用书和培训学校的教材。

图书摘要

版权信息

书名:Java程序设计入门(第2版)

ISBN:978-7-115-53157-5

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [印度]沙姆·蒂克库(Sham Tickoo)

译    郭奇青

责任编辑 陈聪聪

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

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

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

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Introduction to Java Programming, 2nd Edition (9789386551184)

Original edition published by BPB Publications. Copyright (c) 2018 by BPB Publications. Simplified Chinese-language edition copyright (c) 2020 by POSTS & TELECOM PRESS. All rights reserved.

本书中文简体字版由印度BPB Publications授权人民邮电出版社有限公司出版。未经出版者书面许可,对本书任何部分不得以任何方式复制或抄袭。

版权所有,侵权必究。


本书是关于Java语言程序设计的入门图书。全书从Java入门开始,介绍了Java基础,控制语句与数组,类与对象,继承,包、接口和内部类,异常处理,多线程,字符串处理,Applet与事件处理,抽象窗口工具包,Java I/O系统等内容。通过本书的学习,读者可以从零开始认识和掌握Java语言的基本概念和数据结构。

本书不但适用于Java语言的初学者,而且可以作为大专院校相关专业师生的学习用书和培训学校的教材。


Java是Sun Microsystems公司所开发的一门面向对象、独立于平台的多线程编程语言。Java的基本概念来自C和C++,它为用户提供了选择、效率和灵活性。在带来传统易用性的同时,Java还允许有选择地使用新的语言特性,例如平台独立性、安全性、多线程等。最重要的是Java的可移植性,这使它能够在任何操作系统上运行。所有这一切使Java成为学习面向对象编程的强大工具。

本书是一本基于示例的教科书,旨在满足希望了解Java基本概念的初学者和中级用户的需求。书中着重强调了Java是简单、高效的程序创建工具,包括基于窗口和基于Web的程序。

本书的亮点在于其中介绍的每个概念都辅以相应的程序作为示例,以便于读者更好地理解。此外,书中的所有程序都配有逐行讲解,即使没有编程经验的用户也能够弄清楚背后的概念并掌握编程技术,在设计程序时加以灵活运用。

本书的主要特色如下。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

作者和编辑尽最大努力来确保书中内容的准确,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,单击“提交勘误”,输入勘误信息,单击“提交”按钮即可,如下图所示。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者,也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/ submission即可)。

如果您所在的学校、培训机构或企业希望批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为著译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


学习目标

阅读本章,我们将学习如下内容。

本章将介绍Java编程语言,让你能够编写出第一个Java程序。在这一章中,你将简要了解到这门语言的历史、演变、特性,学习如何在系统中安装Java和NetBeans IDE(Integrated Development Environment,集成化开发环境)以及运行Java程序。此外,你还将知晓有关面向对象编程概念的知识及其在Java程序开发中的重要性。


 提示

1.集成化开发环境(Integrated Development Environment,IDE)是一种能够为计算机软件开发人员提供广泛特性的软件,通常由源代码编辑器、自动化构建工具、调试器组成。

2.本书中的Java程序示例都在Windows平台上进行了测试。


Java的第一个版本是由James Gosling于1991年在美国的Sun Microsystems公司(后来被Oracle公司收购)开发的。最初,James Gosling将其命名为Oak,但随后在1995年更名为Java。它的首个版本是为电子设备和电路应用而开发的,该计划获得了成功。后来,这项催生出Java的计划被称为绿色项目(Green project)。

除通用目的外,Java被认为是一种领先的基于Web的技术。在诞生伊始,没有人知道它会有多受欢迎。Java是第一种独立于平台的面向对象编程语言,能够运行于任何平台。它允许开发人员贯彻“一次编写,随处运行”(Write Once, Run Anywhere,WORA)的概念。尽管Java的基本语法取自C和C++,但它仍然与这两者有很大的不同。

Java有4种主要版本。

用于计算机软件的Java应用程序是使用Java标准版开发的,用于Web服务器的Java应用程序是使用Java企业版开发的,用于多媒体平台的应用程序是使用JavaFX开发的,用于移动设备的应用程序是使用Java微型版开发的。

我们可以使用Java编程语言创建小程序(Applet)和应用程序(Application)两种类型的程序。小程序是用于Web浏览器的短小程序代码,属于轻量级的应用程序,通常为浏览器提供增强的导航功能或额外的交互性。

可以使用Java创建的其他类型软件是控制台应用程序(Console Application)。这种应用程序是独立程序,可以像任何其他程序一样在计算机上运行。如NetBeans这样的IDE已经自带了可用于运行Java程序的集成控制台环境。


 提示

不同于独立应用程序,Java小程序不需要任何解释器就能够执行。


Java流行的原因在于其先进的特性,例如平台独立性、简单性和安全性等。我们下面来解释其中一些主要的特性。

1.平台独立性

Java是一种独立于平台的语言,这意味着它可以在任何操作系统上运行。例如,在Windows平台上编写的Java应用程序可以在Linux、Macintosh和其他任何操作系统上运行。当Java在系统上运行时,它会将源代码转换为字节码(byte code)。字节码是由Java编译器在JVM(Java Virtual Machine,Java虚拟机)帮助下生成的,可以在任何系统上独立使用。有关JVM的更多信息,可参见本章后续部分。由于其可移植性,因此在一个平台上用Java创建的应用程序可以在任何其他平台上运行。

2.简单性

与其他语言相比,Java语言的语法非常简单。它与C或C++的语法非常相似。Java中的每个关键字都是有意义的,因此,我们可以轻松识别出关键的操作。

3.两阶段系统

Java分两个阶段编译程序。第一个阶段,Java编译器将源代码转换成字节码。第二个阶段,Java解释器将字节码转换成机器码。因为计算机能够理解机器码,所以就可以执行代码并生成输出。这就叫作两阶段系统(Double Stage System)。

4.面向对象

Java完全是一种面向对象编程语言,因为它将所有一切都视为对象。Java的基本概念取自于C和C++。C并非面向对象编程语言,而是一种基于结构的编程语言。而作为C扩展的C++,则是面向对象编程语言。Java更加独立于C或C++。本章的后续部分将更多地讲解Java、C、C++之间的相似和不同之处。

5.安全性

安全性是编程语言中的一个重要问题。如果应用程序不安全,数据也就不会安全。Java 是一种安全的语言,因为它不像C++那样支持指针,所以代码无法直接访问内存。Java的内部系统会核实试图访问内存的代码。

6.多线程

Java支持多线程,这意味着Java能够在单个进程中处理多项任务。这是Java的重要特性之一。另外,Java 也支持线程同步,这能够帮助多个线程以同步的方式同时工作。本书后续部分将讲解有关多线程的更多内容。

7.易于上手

Java对用户非常友好,而且易于上手。编写Java程序不需要什么特定的环境。我们可以直接在任何文本编辑器中输入Java代码。例如,我们可以在记事本中编写Java程序并保存,然后像编写C或C++程序时那样在命令行窗口中执行这个Java程序。

在谈论面向对象编程系统时,Java的名字总是首当其冲,因为它实现了真正的面向对象编程系统的所有要求,例如,支持数据抽象、封装、多态、继承。

如果一个程序是使用Java等面向对象编程语言创建的,那么类、实例、对象就是这个程序必不可少的组成部分。可以将类定义为描述不同对象的行为/状态的模板/蓝图。对象是展示其类所定义的属性和行为的特定元素。相同类型的对象称为同类型(same type)或同类(same class)。一旦从类派生出对象,就形成了一个实例。对象可以采取的操作称为方法。Java中的方法在其他语言中被称为过程、方法、函数或子程序。

为了理解类和对象的概念,我们假定“车辆”是一个类。在“车辆”类下,可以有不同类型的车辆,例如汽车、公共汽车和卡车等,汽车、公共汽车、卡车就是“车辆”类的对象。

有一些特性促成了面向对象编程的流行。接下来我们就来谈谈这些特性。

用面向对象编程语言的话来说,数据抽象意味着只展示功能,隐藏实现细节。这样做有助于掩饰多种数据的复杂性。在现实世界中,数据抽象的一个例子就是发送电子邮件,用户只需要撰写邮件,然后把它发送给其他用户就可以了,不需要知道背后的内部处理过程。

这是面向对象编程语言的另一个特性。通过封装,方法和数据被组合或包装成为一个单元。换句话说,方法和数据被封装在一起,以称为对象的单个实体形式发挥作用,参见图1-1。这个概念也叫作数据隐藏。在此过程中,数据无法被外部方法或过程访问,只有与其组合在一起的方法才能访问到数据。

图1-1 数据和方法的封装

多态(Polymorphism)是一个希腊词,其中Poly表示“很多”,morph表示“形式”。因此,多态的意思就是“一个名称,多种形式”。在面向对象的概念中,如果单个操作扮演了多种角色,那么它就称为多态。

多态的一个例子是方法重载。在方法重载中,多种方法可以具有相同的名称,但各自拥有不同的参数数量。例如,有一个名为calculate的类,包含了calculate_area(l,b)和calculate_area(s)两个方法。两者的名称都是 calculate_area,但是拥有的参数数量不同。因此,当用户传入两个值时,将调用具有两个参数的方法calculate_area(l,b);当用户传入单个值时,可以调用具有单个参数的方法calculate_area(s)。

继承是面向对象编程的关键特性。它带来的好处是能够重用对象的方法和属性,因而可以减少Java程序的代码行数。如果我们创建了一个类,在其中以属性和方法的形式定义了若干特性。随后,我们需要创建另一个类,该类除现有类的所有特性(属性和方法)之外,还具有一些新的特性(属性和方法)。在这种情况下,无须再单独创建一个类。我们可以从现有类中派生出新类,在新类中添加新特性。这样就能够避免重复同样的代码。

从技术上来说,继承是一种从现有类中派生出新类的技术,可以在新类中重用现有类的特性。派生出的类也称为次类(sub-class)或子类(child class),用于派生出新类的类称为超类(super class)、基类(base class)或父类(parent class)。图1-2通过图示,以简单直观的方式描述了继承的概念。

图1-2 继承的概念

如图1-2所示,Vehicles是一个基类,拥有Two Wheeler和Four Wheeler两个子类。这两个子类分别又拥有Honda和Suzuki、Toyota和BMW两个子类。因此,Two Wheeler和Four Wheeler是其子类的基类,Vehicles是其所有子类的基类。

在Java中,主要包含以下3种继承类型。

1.单一继承

如果从单个父类中派生出单个类,就叫作单一继承。图1-3展示了这一概念,其中,类B继承了类A的属性。

图1-3 单一继承的概念

2.多级继承

如果一个类是从另一个派生类中派生出来的,就叫作多重继承。图1-4展示了这一概念,其中,类C继承了类B的属性,而类B又是类A的子类。

图1-4 多级继承的概念

3.层次继承

如果从单个基类中派生出多个类,就叫作层次继承。图 1-5 展示了层次继承的概念,其中,类B和类C继承了类A的属性。

图1-5 层次继承的概念

在面向对象编程中,还有一种继承类型叫作多重继承(multiple inheritance)。在多重继承中,一个类派生自多个父类。Java的设计者认为这种继承太过复杂,与保持Java简单性的观念不能很好地契合。因此,Java并没有实现多重继承。图1-6展示了多重继承的概念。

图1-6 多重继承的概念

Java能够借助接口实现多重继承的要求。接口是面向对象编程的另一个重要特性,接下来将会讲到。

接口是类的蓝图。它与类非常相似,但只包含抽象方法。抽象方法是仅有声明但不包含任何实现的方法。接口可能也包含常量、方法签名、默认方法、静态方法,但它不具有任何构造函数,因此无法被实例化。接口只能由类来实现或者通过其他接口扩展。类继承接口的抽象方法来实现它。我们可以使用接口实现抽象和多重继承,还可以从任意数量的接口派生类。图 1-7 展示了接口的概念,其中,类C继承了接口A和接口B以及类A的属性。

图1-7 接口的概念

当运行一个Java程序时,它要经历编译和解释两个阶段。在编译期间,源代码被编译器转换成中间语言。源代码是用Java编写的程序,而中间代码是由Java编译器生成的特殊类型代码。中间代码也称为Java字节码或字节码。因为字节码并不针对特定的机器,所以它需要被转换成机器级别的代码,这个任务由Java解释器来完成。Java解释器逐行读取字节码,将其转换为机器代码。这时,再由计算机执行机器代码。


 提示

1.编译器是一种特殊用途的程序,负责将Java程序等高级语言(易于人们书写和理解)转换成低级语言(机器语言)。

2.字节码一种用于Java虚拟机的机器语言。每个计算机平台都有自己的程序来解释字节码指令。


我们已经知道,Java程序的源代码会被转换成字节码,然后再被转换成机器码。字节码不属于任何类型计算机的机器语言。事实上,它是一种叫作Java虚拟机或JVM虚构计算机的机器语言。术语JVM用于指代像虚构计算机那样的软件。

JVM的架构非常强大。只要安装了JDK,JVM就会自动加载到计算机内存中,在编译Java程序时发挥作用。将Java程序转换为机器特定代码的过程表示如图1-8所示。

图1-8 将Java程序转换成机器特定代码的过程表示

在本节中,我们将学习如何在计算机中安装Java SE Development Kit(JDK)以及运行Java程序。安装JDK非常简单,几分钟就能完成。我们可以从Oracle的网站上下载JDK的Windows版本。

一开始,安装程序会提示我们接受许可协议,选择“Accept License Agreement”单选按钮,然后单击与Windows x64条目对应的jdk-8u111-windows-x64.exe,将文件保存在硬盘上。如果我们使用的是32位计算机,则单击与Windows x86条目对应的jdk-8u111-windows-i586.exe链接。文件下载完成后,需要在系统上运行安装程序。在安装过程中,保持默认设置不变。整个过程需要几分钟时间。选择“Finish”按钮以确保完成安装。现在,就可以编写和运行Java程序了。

在系统中安装JDK时,会随之安装如表1-1所列的基础工具。

表1-1 JDK工具清单

工具

描述

javac

Java编译器,用于将Java源代码转换成字节码

java

Java解释器,用于将字节码转换成机器特定代码

javadoc

用于创建HTML文档

appletviewer

用于解释Java applet类

javah

用于编写原生方法

javap

用于反汇编类文件

jdb

Java调试器,用于调试Java程序

jar

用于管理Java归档(Java Archive,JAR)文件

在编写和执行Java程序之前,应该了解要用到的一些基本关键字和语法。Java的大多数关键字与C++类似。我们接下来要讨论其中一些重要的关键字和语法。

Java API(Application Programming Interface,应用程序编程接口)包含大量的类和方法,它们被划分为不同类型的包。Java API用于各种Java应用程序之中。包分为以下两种。

1.内建包

内建包是在Java库中预先定义好的。Java中有各种各样的内建包,它们的用法各不相同。每个Java类都归属于某个包。下面讨论一些广泛用于Java程序中的重要内建包。

(1)Java.lang

这是Java中用得较多的包,它提供了编程中要用到的基础的类,例如Integer、Float、Math、String、Thread等。

(2)Java.IO

这个包用于在Java程序中处理输入和输出文件,包含Reader、Writer、Stream等类。

(3)Java.util

这个包包含了各种实用工具类,涉及数据结构、字符串处理、时间与日期等。

(4)Java.net

这个包用于Java网络编程、套接字编程等。

(5)Java.awt

这个包为基于GUI(Graphical User Interface,图形用户界面)的应用程序提供了各种类。

2.用户自定义包

我们也可以使用package关键字以及有效名称来创建自己的包。通过这种方式创建的包叫作用户自定义包。例如:

package book;
public class JavaBook
{
   public static void main(String[] args)
   {
         System.out.println("Hello Java");
   }
}

在这个例子中,package是关键字,book是包的名称,其中包含一个JavaBook类。要在其他程序中导入并使用这种包,可以使用以下语法:

import book.*

顾名思义,该关键字用于往已有程序中导入包、类或方法。这些包或类可以是用户自定义的,也可以是内建的。举例来说,如果我们没有把包导入已有程序中,那么就无法在其中使用这个包的所有类和方法。因此,我们需要将包导入程序中。

例如:

import java.lang.Math;

该语句导入了lang包的Math类。这是Java的内建包。

我们也可以导入整个包:

import java.lang.*;

*在这里代表包中的所有类。该语句导入了lang包中的全部类。

类是面向对象编程语言的根基,它包含了方法、对象、属性、变量等。class关键字之后跟上有效的类名就可以定义类。

例如:

class JavaBook

该语句使用class定义了名为JavaBook的类。

该语句用于将输出打印到命令提示符的下一行。其中,println是out对象的成员,System指明了类。

例如:

System.out.println("Hello Java");

该语句会在命令提示符的下一行打印出字符串“Hello Java”。


 提示

我们可以使用关键字print来代替关键字println。两者之间唯一的区别是,println是在下一行显示输出,而print是在同一行显示输出。


访问修饰符是用于声明类或方法的关键字,以便在类或包的不同范围内访问。在Java中,有4种类型的访问修饰符,下面对其进行说明。

1.public

如果希望某个类的方法或变量可以由Java程序中的其他类访问,则可以声明public访问修饰符。这些类可以在同一个包中,也可以在其他包中。在所有的修饰符中,public访问修饰符实现了最大范围的访问权限。

例如:

public class JavaBook
public Book() {...........}

2.default

如果没有设置修饰符,则遵循default访问权限。这种访问权限不需要指定修饰符关键字,只能从包内部访问,而不能从包外部访问。

例如:

class JavaBook
Author() {...........}

3.protected

如果希望类的成员既能够在定义其的类内部访问,也能够从由此类派生出的其他类中访问,则可以声明protected访问修饰符。

例如:

protected class JavaBook
protected Author() {...........}

4.private

如果希望类的成员只能由特定的类访问,则可以声明private访问修饰符。

例如:

private class JavaBook
private Author() {...........}

为方便起见,我们可以在Java程序中加入注释。Java支持单行注释和多行注释两种类型的注释,C++同样支持这两种类型的注释。

1.单行注释

如果要在Java程序中书写主题或简短的注释,则可以使用单行注释。这种注释以两条斜线(//)开头。

例如:

//This is a single line comment.

2.多行注释

如果要在Java程序中书写比较长的描述或小型文档,则可以使用多行注释。这种注释出现在/*和*/之间,其中的所有内容都会被编译器忽略。

例如:

/*This is a multiple lines comment. Anything
inside it is ignored by the compiler.*/

能够用来编写和运行Java程序的编辑器有很多。我们可以从中选择一款或者干脆使用记事本(Notepad)来编写。在本节中,我们将学习如何在记事本中编写Java程序,然后在命令行中编译并运行。

首先从 Start(开始)菜单中打开记事本,在其中写入程序代码,然后将文件保存为FirstProgram.java。

示例1-1

下面是一个简单的Java程序示例,该程序将在屏幕上打印出“Hello Java”。

// 该程序将打印Hello Java
1  class FirstProgram
2  {
3        public static void main(String args[ ])
4        {
5               System.out.println("Hello Java");
6        }
7  }

讲解

下面逐行讲解该程序。

第1行

class FirstProgram

该行创建了名为FirstProgram的类。

第2行

{

该行表明开始定义FirstProgram类。

第3行

public static void main(String args[])

所有Java程序中都会用到该语句,它是Java的main()方法,是所有程序的入口点。控制权始终会到达此处。

public

这是访问限定符,表明在整个程序中都可以访问到使用该限定符的方法。

static

static关键字允许在不创建类实例的情况下调用main()方法。这是必不可少的,因为main()方法是在所有对象被创建出来之前由Java解释器调用的。

void

void关键字表明main()方法不返回任何值。

main(String args[])

args[]是string类的对象数组,在这里作为main()方法的参数。

第4行

{

该行表明开始main()方法的定义。

第5行

System.out.println("Hello Java");

该行向屏幕输出“Hello Java”。

第6行

}

该行表明结束main()方法的定义。

第7行

}

该行表明结束FirstProgram类的定义。


 提示

最开始的“//该程序将打印Hello Java”并非程序的组成部分。这是单行注释,仅作参考之用。


编译和运行Java程序一点都不难。我们可以在任何命令行窗口中编译Java程序。在编译和运行Java程序之前,需要知道与此相关的下列两个命令。

1.javac命令

javac命令用于编译Java程序。我们可以按照以下方法使用该命令编译Java程序:

javac Name_of_file with extension

这里,javac是命令名,Name_of_file是后缀为.java的Java程序文件名。

2.java命令

java命令运行编译后的Java程序,在屏幕上显示程序输出。

我们可以像下面一样使用java命令运行Java程序:

java Name_of_file

其中,java是命令名,Name_of_file是程序编译后所生成的Java程序名。注意,在执行java命令时,不用添加Java文件的扩展名。


 提示

最好使用程序中的类名来保存Java程序以避免错误。例如,程序中的类名是FirstName,那么文件名就必须保存为FirstProgram.java。


要编译和运行程序,就必须设置能够定位到JDK二进制文件(如javac或java)的路径(位置)。环境变量path的作用就在于此。

有两种方法可以设置目录路径。第一种方法是设置一个临时路径,这意味着在命令行窗口关闭之前都可以使用该路径。一旦退出,就不能再使用。第二种方法是设置永久路径,这意味着即便是关闭计算机,该路径也不会失效。下面详细讲解这两种方法。

按照下列步骤设置Java程序目录的临时路径。

第1步 在硬盘中创建一个包含所有Java程序的目录并命名,例如Java Projects。

第2步 从Start菜单打开Command Prompt(命令行提示符),进入保存文件的驱动器和目录,例如D盘下的Java Projects目录中的Ch01子目录。如图1-9所示。

图1-9 修改当前驱动器和目录

第3步 在命令行提示符下输入下列命令:

path=The full path of bin directory of Java

其中,path是环境变量名。在赋值操作符后写下Java程序所在的完整路径,然后按回车键,如图1-10所示。这样就设置好了路径。

图1-10 设置临时的Java程序路径

第4步 现在就能够在项目目录中编译和运行程序了。我们可以运行示例1-1来进行测试。重复之前学到的编译和运行方法,该程序即可正常运行。

设置好临时路径之后,示例1-1的输出如图1-11所示。

图1-11 设置好临时路径之后的示例1-1输出


 提示

要返回之前的目录,可以直接在命令行提示符中输入cd \。


按照下列步骤设置Java项目目录的永久路径。[1]

第1步 从Start(开始)菜单中进入Control Panel(控制面板),单击System图标,这时会出现View basic information about your computer窗口,如图1-12所示。或者,右键单击Start菜单中的Computer,然后选择properties来显示View basic information about your computer窗口。

图1-12 View basic information about your computer窗口

第2步 在View basic information about your computer窗口中选择Advanced system setting,这时会出现System Properties对话框,如图1-13所示。

图1-13 System Properties对话框

第3步 在System Properties对话框中,选择Advanced标签,然后单击Environment Variables按钮,这时会出现Environment Variables对话框,如图1-14所示。

图1-14 Environment Variables对话框

第4步 在System variables区域单击New按钮,这时会出现New System Variable输入框。

第5步 在Variable name文本框中输入PATH,在Variable value文本框中输入JDK的bin目录的完整路径,然后单击OK按钮,如图1-15所示。

图1-15 New System Variable文本框

再次单击Environment Variables对话框中的OK按钮,然后单击System Properties对话框中的OK按钮。

至此,永久路径设置完毕,我们可以在命令行提示符中随处编译和运行Java程序了。

设置好永久路径之后的示例1-1输出如图1-16所示。

图1-16 设置好永久路径之后的示例1-1输出

NetBeans IDE是一款流行的开源IDE,可以用来轻松快速地进行Java、JavaScript、HTML5、PHP、C/C++等语言的桌面、移动、Web应用开发。大多数程序员选择IDE的原因在于,无须再单独使用文本编辑器、编译器、运行器等工具。

IDE通过图形用户界面将以上所有这些工具集成在了一起。网上有很多可用的IDE,其中一些拥有自己的编译器和虚拟机。

要安装NetBeans,可进入Oracle官网找到Java SE的下载页面,然后单击NetBeans with JDK 8条目对应的Download按钮,如图1-17所示。

图1-17 NetBeans下载链接

在接下来的页面中,选择Accept License Agreement单选按钮,然后单击与Windows x64条目对应的jdk-8u73-nb-8_1-windows-x64.exe。保存该文件。如果使用的是32位计算机,则单击与Windows x86条目对应的jdk-8u73-nb-8_1-windows-i586.exe。双击jdk-8u73-nb-8_1-windows-x64.exe文件开始安装,系统会提示是否接受许可协议。选择接受并继续进行其余的安装过程。NetBeans快捷方式图标会出现在桌面上。双击该图标,即可进入NetBeans的界面,如图1-18所示。

图1-18 NetBeans的界面

在NetBeans中编写Java程序的第一步是创建一个新的空项目。为此,在菜单中选择File > New Project,打开New Project对话框,如图1-19所示。

图1-19 New Project对话框

在这个对话框中,选择Categories中的Java以及Projects列表中的Java Application,然后单击Next按钮,接着会出现New Java Application对话框,如图1-20所示。

图1-20 New Java Application对话框

在该对话框的Name and Location部分,在Project Name对话框中输入项目名称NetProgram。如果要更改项目位置,可以在Project Location字段中选择Browse按钮,然后选择Finish按钮,关闭对话框,创建项目。

项目显示在左侧的Projects窗口中,如图1-21所示。

图1-21 Projects窗口中显示的NetProgram项目

NetBeans的NetProgram.java标签下显示的代码如下:

1   /*
2   * To change this license header, choose License Headers in Project Properties.
3    * To change this template file, choose Tools | Templates
4    * and open the template in the editor.
5    */
6    package netprogram;

7    /**
8    *
9    * @author CADCIM
10   */
11   public class NetProgram {

12       /**
13       * @param args the command line arguments
14       */
15       public static void main(String[] args) {
16              // TODO code application logic here
17              System.out.println("Cadcim Technologies");
18       }
19   }

讲解

下面逐行讲解该程序。

第1行~第5行

/*

*To change this license header, choose License Headers in Project Properties.

*To change this template file, choose Tools | Templates

*and open the template in the editor.

*/

这几行是多行注释。编辑器会忽略/*和*/之间的所有内容。

第6行

package netprogram;

该行定义了类所属的包。其中,package是关键字,netprogram是包的名称。

第7行~第10行

/**

*

*@author CADCIM

*/

这几行也是会被编译器忽略的多行注释。

第11行

public class NetProgram{

在这一行中,public是访问限定符,表明在整个程序中都可以访问。class是关键字,NetProgram是类名,左花括号表明开始定义类。

第12行~第14行

/**

*@param args the command line arguments

*/

这几行也是会被编译器忽略的多行注释。

第15行

public static void main(String[] args) {

该行中所包含的main()方法被视为所有Java程序执行时的起始点。左花括号表明开始定义main()方法。

第16行

// TODO code application logic here

该行为单行注释,会被编译器忽略。

第17行

System.out.println("Cadcim Technologies");

该行会在Java程序运行时在屏幕上输出“Cadcim Technologies”。

第18行

}

该行表明main()方法的定义已经结束。

第19行

}

该行表明NetProgram类的定义已经结束。

在菜单中选择Run > Run Project或按F6即可运行项目。如果运行成功,BUILD SUCCESSFUL消息会出现在NetBeans界面底部的Output窗口。如果程序中有错误,该窗口中会显示错误信息。我们需要修改错误,然后重新构建程序。

显示在NetBeans界面底部的Output窗口中的输出如下:

Cadcim Technologies
BUILD SUCCESSFUL (total time: 0 seconds)

回答以下问题,然后将其与本章末尾给出的问题答案比对。

1.Java最初的时候叫作什么?

 (a)Aok    (b)Oak    (c)Ako    (d)Oka

2.Java可以运行在哪些平台?

 (a)Linux           (b)Windows

 (c)Mac          (d)以上所有平台

3.Java不支持以下哪一种继承?

 (a)多级继承        (b)多重继承

 (c)单一继承        (d)层次继承

4.Java支持下列哪一项?

 (a)数据抽象  (b)封装   (c)多态    (d)以上所有

5.如果多个类派生自一个父类,那么这种继承叫作什么?

 (a)单一继承        (b)多级继承

 (c)层次继承        (d)多重继承

6.下列哪个命令可用于编译Java程序?

 (a)java    (b)javap   (c)javac   (d)jvm

7.术语IDE代表__________。

8._________有助于隐藏数据复杂性。

9.在封装中,方法和数据被组合成为一个单元。(对/错)

10.Java小程序无须解释器就可以执行。(对/错)

11.javac命令用于解释Java程序。(对/错)

12.在执行Java命令时,不需要添加文件扩展名.java。(对/错)

回答下列问题。

1.什么是字节码?它是如何产生的?

2.javac和java命令的用法是什么?

3.什么是JVM?JVM如何处理字节码?

4.Java中的关键字import有什么作用?

5.检查下列程序中的语法错误并更正,给出该程序的输出结果:

Class Hello
{
   Public static void main(String args[ ])
   {
         system.out.println("Hello")
         System.out.print('Welcome to the exciting world of Java');
   }
}

6.下面两条语句有什么不同?

System.out.print("Hello World!");
System.out.println("Hello World!");

练习

编写程序,在屏幕上输出下列语句。

Java is an interesting language.

It is easy to learn.

 

 

 

 

自我评估测试答案

1.b 2.d 3.b 4.d 5.c 6.c 7.Integrated Development Environment 8.数据抽象 9.对 10.对 11.错 12.对

[1] 译文按照原书,以英文版Windows 7演示设置步骤。


学习目标

阅读本章,我们将学习如下内容。

在本章中,我们将学习到Java的基础知识,例如标识符、关键字、字面量、数据类型、变量、运算符等。标识符是包、类、方法、变量的名称。关键字是具有特殊含义的标识符。字面量描述了保存在变量中的固定值。数据类型指定了所保存的数据种类以及数据的取值范围。变量是数据的存储位置,数据可以保存在其中。运算符是用于描述某种操作的符号。另外,我们还将学习有关类型转换的概念。

Java的所有组成部分都需要名称。因此,标识符就是包、类、方法、变量的名称。要命名一个标识符,必须遵循以下规则。

以下标识符都是有效的Java变量名:

idname_6
id_name
_idname

以下标识符都是无效的Java变量名:

6_idname    //以数字开头
idname#     //使用了特殊字符#
id name     //使用了空格

Java编程语言中有一些保留的关键字不能用作标识符,因为它们对于编译器而言具有特殊含义。由于关键字在Java中所发挥的特定功能,因此大多数Java IDE会使用各种颜色着重显示这些关键字,以便程序员一目了然。

Java的50个关键字如下:

abstract   assert    boolean  break    byte

case     catch    char    class     const

continue    default     do      double    else

enum    extends    final    finally    float

for      goto     if      implements import

instanceof   int      interface  long      native

new      package    private    protected  public

return    short      static    strictfp    super

switch    synchronized  this    throw    throws

transient  try       void    volatile   while

关于Java关键字,有下列几点重要之处需要指出。

数据类型描述了保存在变量中的值的大小和种类。在任何程序中,都需要在内存中保存特定类型的数据。编译器应该知道需要分配给特定数据的内存单元数量。为此,就要用到数据类型。数据类型的作用是指导编译器为特定类型的数据分配相应的内存。Java是强类型语言,这意味着每种数据类型都已经作为语言的一部分预先定义好。Java的数据类型分为3类。


 提示

本章随后将讨论变量。


原始数据类型是由Java编程语言预先定义的,属于基本数据类型。这些类型需要声明,用于描述单一值,不能描述多个值。Java提供了8种原始数据类型。

这些原始数据类型被划分为4类,下面我们逐一讨论。


 提示

在大多数编程语言中,例如C++,分配给特定数据类型的内存数量取决于机器架构。但是在Java中,所有数据类型的大小都是严格定义好的,不依赖于机器架构。


1.整数类型

整数类型仅用于那些不包含任何小数部分或小数点的数字。换句话说,这种数据类型仅用于带符号的整数,包括负数和正数。Java定义了byte、short、int、long共4种整数类型,它们之间的主要区别在于分配给每种类型的内存数量以及每种类型可以存储的数值范围。表 2-1 显示了所有整数类型的大小和取值范围。

表2-1 整数类型的大小和取值范围

整数类型名称

大小(字节数)

取值范围

byte

1

−128~127

short

2

−32 768~32 767

int

4

−2 147 483 648~2 147 483 647

long

8

−9 223 372 036 854 775 808~9 223 372 036 854 775 807

(1)byte

byte是最小的整数类型。byte类型的大小是8位(bit)(1字节等于8位),取值范围为−128~127。这里,取值范围意味着byte类型能够保存的最小值是−128、最大值是127。这种数据类型非常适用于在Java中处理文件或流。可用于在大型数组中节省空间。我们可以使用byte关键字以及变量名来创建byte类型的变量:

byte var_name;

在该语法中,变量var_name被声明为byte类型。

(2)short

short类型在Java中很少用到。short类型的大小是16位(2字节),取值范围为−32 768~32 767。这种类型能够节省不少空间。我们可以像下面一样创建short类型的变量:

short var_name;

在该语法中,变量var_name被声明为short类型。

(3)int

在整数类型中,int是Java中用得比较多的类型。int类型的大小是32位(4字节),取值范围为−2 147 483 648~2 147 483 647。除非对内存有所顾虑,否则通常将整数类型作为整数值的默认类型。我们可以像下面一样创建int类型的变量:

int var_name;

在该语法中,变量var_name被声明为int类型。

(4)long

在整数类型中,long是最大的类型。当int类型不足以容纳某些整数值的时候,就需要用到这种类型。long类型的大小是64位(8字节),取值范围为−9 223 372 036 854 775 808~9 223 372 036 854 775 807。我们可以像下面一样创建long类型的变量:

long var_name;

在该语法中,变量var_name被声明为long类型。

2.浮点类型

浮点类型仅用于那些包含小数部分或小数点的数字。这种数字也称为实数。在Java中,定义了float和double两种浮点类型。表2-2显示了这两种类型的大小和取值范围。

表2-2 浮点类型的大小和取值范围

浮点类型名称

大小(字节数)

取值范围(近似)

float

4

1.40e−45~3.40e+38

double

8

4.9e−324~1.8e+308

(1)float

float类型用于单精度值(小数点后最多8位)。float类型的大小是32位(4字节),取值范围从1.40e−45~3.40e+38。我们可以像下面一样创建float类型的变量:

float var_name;

在该语法中,变量var_name被声明为float类型。

(2)double

顾名思义,double类型用于双精度值(小数点后最多15位)。这种类型多用于希望得到精确结果的科学计算。double类型的大小是64位,取值范围从4.9e−324~1.8e+308。我们可以像下面一样创建double类型的变量:

double var_name;

在该语法中,变量var_name被声明为double类型。

3.字符类型

char类型属于其中的一类。在Java中,char类型用于保存能够由字母、数位、特殊符号描述的单个字符值。

char

如前所述,char类型用于保存属于Unicode字符集的字符值。但是Java中的char类型与其他编程语言(如C/C++等)中的char类型完全不同。在C /C++中,char类型的大小是8位(1字节),只能支持英语、德语等少数字符集。在Java中,char类型的大小是16位(2字节),用于保存Unicode字符集的值[1]。Unicode字符集包含了人类语言中的用到所有字符。char类型的取值范围为0(最小)~65 535(最大)。我们可以像下面一样创建char类型的变量:

char var_name;

在该语法中,变量var_name被声明为char类型。


 提示

赋值给char类型变量的字符应该放入单引号中。


4.布尔类型

原始数据类型boolean同样是该分类中的一员。这种类型可用于保存真值或假值。

boolean

该类型只能保存一个值——true或false。boolean类型的大小是1位。这种类型仅用于保存逻辑值。在默认情况下,它返回false。我们可以像下面一样创建boolean类型的变量:

boolean var_name;

在该语法中,变量var_name被声明为boolean类型。

派生数据类型的变量能够保存多个相同类型的值,但无法保存多个不同类型的值。其中所包含的值可以是原始数据类型。派生数据类型的代表是数据和字符串。

例如:

int a[]={10, 20, 30};   //有效数组
int b[]={10,10.5,'A'};  //无效数组
char carray[]={'c','a','d','c','i','m'};

用户自定义类型变量中可以保存多个同类型或不同类型的值。这种数据类型由程序员通过该语言的相应特性来定义。类和接口就属于用户自定义数据类型。


 提示

我们将在之后的章节中学习到数组、字符串、类以及接口。


转义序列是用于向设备或程序发送指示的字符序列。这种序列以反斜线(\)起始,该字符叫作转义字符。转义序列不仅可用于文本格式化,而且可用于特殊目的。表2-3中显示了Java中所使用的转义序列清单。

表2-3 转义序列清单

转义序列

描述

\t

插入制表符

\\

插入反斜线

\'

插入单引号

\"

插入双引号

\r

插入回车

\n

插入新行

\b

插入退格符

\f

插入换页(form feed)

示例2-1

下面的程序展示了转义序列的用法。

//编写程序,展示转义序列的用法
1   class Escape
2   {
3      public static void main(String arg[])
4      {
5          System.out.println("Linefeed       : \nLearning Java");
6          System.out.println("Single Quote   : \‘Learning Java\’");
7          System.out.println("Double Quote   : \"Learning Java\"");
8          System.out.println("Backslash      : \\Learning Java\\");
9          System.out.println("Horizontal Tab : Learning\tJava");
10         System.out.println("Backspace      : Learning\bJava");
11         System.out.println("Carriage Return: Learning\rJava");
12     }
13  }

讲解

第1行

class Escape

在该行中,class关键字定义了一个名为Escape的新类。

第3行

public static void main(String arg[])

该行中所包含的main()方法被视为所有Java程序执行时的起始点。程序从这一行开始执行。

第5行

System.out.println("Linefeed : \nLearning Java");

该行会在屏幕上显示下列内容:

Linefeed :

Learning Java

第6行

System.out.println("Single Quote : \'Learning Java\'");

该行会在屏幕上显示下列内容:

Single Quote : 'Learning Java'

第7行

System.out.println("Double Quote : \"Learning Java\"");

该行会在屏幕上显示下列内容:

Double Quote : "Learning Java"

第8行

System.out.println("Backslash : \\Learning Java\\");

该行会在屏幕上显示下列内容:

Backslash : \Learning Java\

第9行

System.out.println("Horizontal Tab : Learning\tJava");

该行会在屏幕上显示下列内容:

Horizontal Tab : Learning Java

第10行

System.out.println("Backspace : Learning\bJava");

该行会在屏幕上显示下列内容:

Backspace : LearninJava

第11行

System.out.println("Carriage Return: Learning\rJava");

该行会在屏幕上显示下列内容:

Javaiage Return: Learning

示例2-1的输出如图2-1所示。

图2-1 示例2-1的输出

变量是能够保存数据的具名位置。它在计算机内存中拥有特定的地址,可在需要时存储和检索值。在程序执行时,变量的值可能会有所不同。

在程序中,变量在使用之前必须先声明。变量声明的语法如下:

data_type var_name;

该语法将声明分为两部分。第一部分的data_type代表数据类型,指定了变量中所存储值的类型以及要为其分配的内存数量。第二部分的var_name代表变量名。变量命名需要遵循一些规则。如前所述,标识符是变量、类等所使用的名称。变量名的规则与先前讲过的标识符规则一样。

例如,我们可以声明一个整型变量age:

int age;

执行该语句时,编译器会为变量age分配4字节(int类型的大小是4字节)的内存。现在,变量age就可以用来引用已分配的内存位置。

我们也可以在单个语句中声明多个同类型的变量,这些变量之间以逗号分隔。语法如下:

data_type var1, var2, var3;

其中,var1、var2、var3被声明为具有数据类型data_type的变量。这里,所有3个变量的类型都相同。

例如:

float highest_temp, lowest_temp;

在这个例子中,highest_temp和lowest_temp均为float类型的变量。

初始化意味着为变量分配初始值。变量的赋值可以通过赋值运算符(=)完成。本章随后将讨论赋值运算符。变量初始化的语法如下:

data_type var_name = value;

在该语法中,data_type指定了数据类型,var_name指定了变量名,value指定了分配给var_name的初始值。

例如:

char ch = 'y';

在这个例子中,字符值y被作为初始值分配给字符变量ch。现在,字符值y就保存在由变量ch所引用的内存位置中。

在本节中,变量是在声明时初始化的。在Java中,也可以动态地(在程序执行过程中)初始化变量。

例如:

int sum = a+b;

在执行该语句时,变量a和b的值通过加法运算符(+)相加。接着,相加的结果被赋给整数类型变量sum。


 提示

所涉及的运算符将在本章随后部分讨论。


示例2-2

下面的程序演示了变量动态初始化的概念。该程序计算3个数的平均值,将结果分配给另一个变量,然后将其显示在屏幕上。

//编写程序,计算3个数的平均值
1   class average
2   {
3      public static void main(String arg[])
4      {
5         int a=10, b=14, c=33;
6         float avg;
7         avg= (a+b+c)/3; //动态初始化变量avg
8         System.out.println("The average of three numbers is: "  +avg);
9      }
10  }

讲解

第5行

int a=10, b=14, c=33;

在该行中,a、b、c被声明为整数类型,通过赋值运算符(=)将其初始值分别设置为10、14、33。

第6行

float avg;

在该行中,avg被声明为float类型的变量。

第7行

avg=(a+b+c)/3;

该行动态初始化了变量avg。其中,先将变量a、b、c的值相加,然后用得到的变量之和57除以3。接下来,在程序执行期间将结果19.0赋给变量avg。

第8行

System.out.println("The average of three numbers is:" +avg);

该行会在屏幕上显示下列内容:

The average of three numbers is: 19.0


 提示

第8行中,符号+用于将变量avg的值拼接到指定的字符串之后。


示例2-2的输出如图2-2所示。

图2-2 示例2-2的输出

在Java中有4种类型的变量。

1.局部变量

局部变量是在代码块或方法内部声明的变量。

局部变量有以下限制。

例如:

int mul( )
{
   int a=10, b=10, c;
   c=a*b;
}

在这个例子中,mul()是一个方法,变量a、b、c是在其中声明的变量。这些变量是该方法的局部变量,只能在该方法内访问或操作。我们将在后续章节中学到与方法、构造函数、访问修饰符相关的更多内容。

2.实例变量

在类内部(但是在该类的其他方法之外)声明的变量称为实例变量。这种变量与类的单个实例相关。实例变量可供同类中的不同方法使用,也叫作非静态成员变量。

例如:

class Demo
{
   public static void main(String arg[])
   {
      int a, b;
      ----------;
   }
}

在这个例子中,变量a和b是在类的内部,但是在该类的其他方法之外声明的。因此,被视为实例变量,可以被Dmeo类的其他方法使用。

3.类/静态变量

除声明时需要使用static关键字外,类变量和实例变量并没什么两样。这种变量不能是局部的。不管一个类被实例化多少次,都只会创建一份静态或类变量的副本。我们将在后续章节中学到与static相关的更多内容。

例如:

class Demo
{
   public static void main(String arg[])
   {
      static int a, b;
      ----------;
      ----------;
   }
}

在这个例子中,使用static关键字声明了变量a和b,两者因此被视为类变量。

4.方法参数变量

在方法声明签名(method declaration signature)中声明的变量称为方法参数变量(methond parameter variable)。只要某个方法被调用,就会创建与其声明时同名的变量。与局部变量一样,这种变量也没有默认值,因此应该对其进行初始化,否则编辑器将报错。

例如:

void demo_method( int a, int b)
{
   -----------;
   -----------;
}

在这个例子中,demo_method()是一个方法,变量a和b是该方法的参数。

public static void main(String arg[ ])是所有Java程序的执行入口,变量arg是该方法的参数。要记住的一件重要事情是,参数总是被归类为“变量”(variable)而不是“字段”(field)。这适用于在后续章节中学到的其他参数(如构造函数和异常处理程序)。

变量的作用域指的是程序中可以对其进行访问和操作的部分。作用域还指定了何时为变量分配或销毁内存。生命期指定了变量在计算机内存中的寿命。前面讨论的4种类型的变量具有不同的作用域和生命期。局部变量的范围仅限于声明它的代码块或方法,并且局部变量的生命期仅从执行代码块或方法时才开始。一旦执行完毕,局部变量就从计算机内存中销毁。

类型转换(type conversion)意味着将一种数据类型转换成另一种数据类型,也称为类型强转(type casting)[2]。例如,借助类型转换,byte类型的数据可以转化成int类型。Java支持两种类型转换。

如果目标数据类型大于源数据类型,而且两种数据类型相容,则进行隐式转换。这也叫作自动转换。例如,short类型的数据转换成int类型。在这种情况下,Java执行隐式转换,因为int类型大于short类型且两种类型相容。在隐式转换过程中,不会出现信息丢失的现象。

示例2-3

下面的程序利用隐式转换的概念将byte类型的数据转换成int类型,并在屏幕上显示转换结果。

//编写程序,将byte类型的数据转换成int类型
1   class Type_demo
2   {
3      public static void main(String arg[])
4      {
5          byte src = 127;
6          int dest;
7          dest = src;
8          System.out.println("dest = " +dest);
9      }
10  }

讲解

第5行

byte src = 127;

在该行中,src被声明为byte类型的变量并被初始化为127。

第6行

int dest;

在该行中,dest被声明为int类型的变量。

第7行

dest = src;

在该行中,发生了隐式转换,变量src的值127被赋给int类型变量dest。

第8行

System.out.println("dest = " +dest);

该行会在屏幕上显示下列内容:

dest = 127

示例2-3的输出如图2-3所示。

图2-3 示例2-3的输出

在第2.7.1节中,我们已经知道了目标类型大于源类型时的类型转换。但有时候,可能需要将较大的数据类型转换为较小的数据类型。例如,将int类型转换为byte类型。对于这种情况,要用到显式转换。在显式转换中,总是会丢失某些信息。因此,这种类型转换也称为收窄转换(narrowing conversion)。显式转换的语法如下:

(destination_data_type) value

其中,destination_data_type指定了要转换的目标数据类型,value指定了要转换的值。


 窍门

显示转换的经验法则是两侧的数据类型应该相同。


例如,我们可以将int类型的值转换成byte类型:

byte b;
int i = 300;
b = (byte) i;

在这个例子中,括号中的byte告诉编译器将int类型变量i的值转换成byte类型。然后,将转换后的结果赋给byte类型的变量b。

示例2-4

下面的程序利用显式转换的概念将int类型的数据转换成byte类型,并在屏幕上显示转换结果。

//编写程序,将int类型转换成byte类型
1   class Explicit_demo
2   {
3      public static void main(String arg[])
4      {
5         byte b;
6         int val = 300;
7         b = (byte) val;
8         System.out.println("After conversion, value of b is: " +b);
9      }
10  }

讲解

第5行

byte b;

在该行中,b被声明为byte类型的变量。

第6行

int val = 300;

在该行中,val被声明为int类型的变量并被初始化为300。

第7行

b = (byte) val;

在该行中,变量val的值被转换为byte类型,因为byte是目标类型。转换结果被赋给变量b。

第8行

System.out.println("After conversion, value of b is: " +b);

该行会在屏幕上显示下列内容:

After conversion, value of b is: 44

示例2-4的输出如图2-4所示。

图2-4 示例2-4的输出


 提示

布尔类型的值不能赋给其他类型。布尔类型不适用于转换。该类型的值只能赋给同类型的变量。


运算符被定义为各种符号,在对变量或常量执行运算的时候使用。Java提供了丰富的运算符,这些运算符可以分为多类。

单目运算符因只需要一个操作数而得名。表2-4列出了Java中的所有单目运算符。

表2-4 单目运算符及其语法

运算符

描述

语法

+

单目加运算符;表示正值(没有该运算符的数字依然是正数)

var1=+var2

单目减运算符;表示负值

var1=−var2

++

增量运算符;增加1

var1=var2++,var1=++var2

− −

减量运算符;减少1

var1=var2− −,var1=− −var2

!

单目取反运算符;对布尔值求反

!var1

增量运算符(++)与减量运算符(− −)

运算符++可将操作数的值加1,运算符− −可将操作数的值减1,语法如表2-4所示。

这两个运算符有两种写法。

(1)后缀写法

在后缀写法中,增量或减量运算符出现在操作数之后。语法如下:

var1++;     //增量
var1--;     //减量

在该语法中,出现在变量var1之后的增量运算符(++)和减量运算符(− −)可将var1的值增加或减少1。

如果在表达式中采用后缀写法,那么操作数的值首先被赋给左侧的变量,然后对该操作数执行加1或减1的操作。

例如:

y = x--;

在这个例子中,变量x的值先被赋给变量y,然后x再减1。

下面两条语句与语句y = x− −产生的结果是一样的。

y = x;
x = x-1;

(2)前缀写法

在前缀写法中,增量或减量运算符出现在操作数之前。语法如下:

++var1;
--var1;

在该语法中,出现在变量var1之前的增量运算符(++)和减量运算符(− −)可将var1的值增加或减少1。

如果在表达式中采用前缀写法,那么首先对操作数执行加1或减1的操作,然后将结果赋给左侧的变量。

例如:

y = --x;

在这个例子中,变量x的值先被减1,然后被赋给变量y。

下面两条语句与语句y = − −x产生的结果是一样的。

x = x-1;
y = x;

示例2-5

下面的程序将执行所有的单目运算并将结果显示在屏幕上。

//编写程序,执行各种单目运算
1   class UnaryOp_Demo
2   {
3      public static void main(String[] arg)
4      {
5         int result,res = +10;
6         System.out.println("Unary plus Operator result is " +res);
7         res = -res;
8         System.out.println("Unary Minus Operator result is " +res);
9         result = res++;
10        System.out.println("Post-increment result is " +result);
11        result = ++res;
12        System.out.println("Pre-increment result is " +result);
13        result = res--;
14        System.out.println("Post-decrement result is " +result);
15        result = --res;
16        System.out.println("Pre-decrement result is " +result);
17        boolean success = false;
18        System.out.println("Result without compliment operator is " +success);
19        System.out.println("Result with compliment operator is "+!success);
20     }
21  }

讲解

第5行

int result,res = +10;

在该行中,result和res被声明为int类型的变量,res被初始化为+10。+是表示正值的单目运算符。如果不使用此运算符,值仍然是正数。

第6行

System.out.println("Unary plus Operator result is " +res);

该行会在屏幕上显示下列内容:

Unary plus Operator result is 10

第7行

res = -res;

在该行中,使用单目减运算符(−)将变量res的值修改成负数。

第8行

System.out.println("Unary Minus Operator result is " +res);

该行会在屏幕上显示下列内容:

Unary Minus Operator result is -10

第9行

result = res++;

在该行中,首先将变量res的值(−10)赋给变量result,然后变量res的值加1。

第10行

System.out.println("Post-increment result is " +result);

该行会在屏幕上显示下列内容:

Post-increment result is10

第11行

result = ++res;

在该行中,首先把变量res的值(−9)加1,然后将其赋给变量result。


 提示

在第10行中,输出是−10。但在第11行中,res的初始值是−9。因为在后缀写法中,是先赋值,然后加1,所以第10行输出的是赋值后的值,加1后的值(−9)被保存在内存中。


第12行

System.out.println("Pre-increment result is " +result);

该行会在屏幕上显示下列内容:

Pre-increment result is -8

第13行

result = res--;

在该行中,首先将变量res的值(−8)赋给变量result,然后变量res的值减1。

第14行

System.out.println("Post-decrement result is " +result);

该行会在屏幕上显示下列内容:

Post-decrement result is -8

第15行

result = --res;

在该行中,首先把变量res的值(−9)减1,然后将其赋给变量result。

第16行

System.out.println("Pre-decrement result is " +result);

该行会在屏幕上显示下列内容:

Pre-decrement result is -10

第17行

boolean success = false;

在该行中,success被声明为布尔类型变量并被初始化为false。

第18行

System.out.println("Result without compliment operator is " +success);

该行会在屏幕上显示下列内容:

Result without compliment operator is false

第19行

System.out.println("Result with compliment operator is " +!success);

该行会在屏幕上显示下列内容:

Result with compliment operator is true

示例2-5的输出如图2-5所示。

图2-5 示例2-5的输出

用于数学表达式中的运算符称为算术运算符。表2-5列出了Java中的所有算术运算符。

表2-5 算术运算符及其语法

运算符

描述

语法

+

加法

var1=var2+var3

减法

var1=var2−var3

*

乘法

var1=var2*var3

/

除法

var1=var2/var3

%

求模;得到余数

var1=var2%var3

示例2-6

下面的程序利用算术运算符对两个数字执行加法、减法、乘法、除法以及求模运算,并在屏幕上显示结果。

// 编写程序,使用算术操作符对两个数字执行各种算术操作
1   class Arith_operators
2   {
3      public static void main(String arg[])
4      {
5          int val1 = 30, val2 = 10;
6          int sum = val1+val2;
7          int sub = val1-val2;
8          int mul = val1*2;
9          int div = val1/val2;
10         int mod = mul%7;
11         System.out.println("Value 1 = " +val1);
12         System.out.println("Value 2 = " +val2);
13         System.out.println("Addition = " +sum);
14         System.out.println("Subtraction = " +sub);
15         System.out.println("Multiplication = " +mul);
16         System.out.println("Division = " +div);
17         System.out.println("Modulus = " +mod);
18     }
19  }

讲解

第5行

int val1 = 30, val2 = 10;

在该行中,var1和var2被声明为整数类型变量并分别被初始化为30和10。

第6行

int sum = val1+val2;

在该行中,变量var1的值(30)与变量var2的值(10)相加,将结果(40)赋给整数类型变量sum。

第7行

int sub = val1-val2;

在该行中,从变量var1的值(30)中减去变量var2的值(10),将结果(20)赋给变量sub。

第8行

int mul = val1*2;

在该行中,变量var1的值(30)乘以2,将结果赋给整数类型变量mul。

第9行

int div = val1/var2;

在该行中,变量val1的值(30)除以变量val2的值(10),将商(3)赋给整数变量div。

第10行

int mod = mul%7;

在该行中,变量mul的值(60)除以7,将余数(4)赋给整数类型变量mod。因此,mul%7的范围余数值4。

第11行

System.out.println("Value 1 =" +val1);

该行会在屏幕上显示下列内容:

Value 1=30

第12行~第17行的工作方式与第11行类似。

示例2-6的输出如图2-6所示。

图2-6 示例2-6的输出

数据以0和1的形式存储在计算机的内存中,这称为位。例如,字节值3以00000011的形式存储在内存中。为了实现单独操作这些位,Java提供按位运算符。按位运算符用于对操作数的单个位进行操作。这种运算符主要应用于整数类型,例如byte、short、int和long。它们也可以应用于char类型。表2-6显示了所有的按位运算符。

表2-6 按位运算符

运算符

操作

按位求补

&

按位AND

|

按位OR

^

按位XOR

>>

右移

<<

左移

>>>

零填充右移

1.按位求补运算符

按位求补(~)运算符属于按位逻辑运算符类别。~运算符会将操作数的所有位取反,例如,0变成1,1变成0。该运算符也称为按位单目NOT运算符。语法如下:

~ value or expression;

例如:

int a = 3;
int b = ~a;

在这个例子中,整数类型变量被初始化为3,该值在计算机内存中以00000011形式保存。在下一条语句中,~运算符的操作数是整数类型变量a。该运算符将数值3所对应的二进制位00000011全部取反,结果为11111100,然后将其赋给整数类型变量b。

2.按位AND(&)运算符

按位 AND(&)运算符属于按位逻辑运算符类别。如果两个操作数都是 1,&运算符的结果为1;如果两个操作数中的一个为0,则&运算符的结果为0。&运算符的语法如下:

operand1 & operand2;

例如,我们可以像下面一样对两个操作数(23和15)使用AND(&)运算符:

    00010111    //23所对应的二进制位
  & 00001111    //15所对应的二进制位
    --------
    00000111    //7所对应的二进制位

3.按位OR(|)运算符

按位OR(|)运算符属于按位逻辑运算符类别。如果有一个或两个操作数都为1,|运算符的结果为1;如果两个操作数都为0,则|运算符的结果为0。|运算符的语法如下:

operand1 | operand2;

例如,我们可以像下面一样对两个操作数(23和15)使用OR(|)运算符:

    00010111    //23所对应的二进制位
  | 00001111    //15所对应的二进制位
    --------
    00011111    //31所对应的二进制位

4.按位异或(^)运算符

按位异或(^)运算符或XOR运算符属于按位逻辑运算符类别。如果其中一个操作数为1,^运算符的结果为1;否则,结果为0。^运算符的语法如下:

operand1 ^ operand2;

例如,我们可以像下面一样对两个操作数(23和15)使用XOR(^)运算符:

    00010111    //23所对应的二进制位
  ^ 00001111    //15所对应的二进制位
    --------
    00011000    //24所对应的二进制位

表2-7描述了所有的按位逻辑运算符(&、|、^、~)。

表2-7 按位逻辑运算符

X Y X&Y X|Y X^Y ~X
0 0 0 0 0 1
0 1 0 1 1 1
1 0 0 1 1 0
1 1 1 1 0 0

除按位逻辑运算符以外,还有下列运算符可用。

5.右移(>>)运算符

右移(>>)运算符用于将操作数的所有位向右移动。>>运算符按照指定的次数移动位,语法如下:

value or expression >> num

在该语法中,num指定了要执行右移操作的次数,val或expression指定了操作数。

例如:

int a = 17;
int b = a>>2;

操作过程如下:

00010001    //17所对应的二进制位

当>>运算符对操作数执行第一次操作时,会丢失最右侧的位(1),其他所有的位向右移动。在此之后形成的位模式如下:

00001000    //8所对应的二进制位

在第二步中,重复与第一步相同的过程,最后形成的位模式如下:

00000100    //4所对应的二进制位

6.左移(<<)运算符

左移(<<)运算符用于将操作数的所有位向左移动。<<运算符按照指定的次数移动位,语法如下:

value or expression << num

在该语法中,num指定了要执行左移操作的次数,val或expression指定了操作数。

例如:

int a = 17;
int b = a<<2;

操作过程如下:

00010001  //17所对应的二进制位

当<<运算符对操作数执行第一次操作时,会丢失最左侧的位(0),其他所有的位向左移动。在此之后形成的位模式如下:

00100010  //34所对应的二进制位

在第二步中,重复与第一步相同的过程,最后形成的位模式如下:

01000100  //68所对应的二进制位

7.零填充右移(>>>)运算符

零填充右移(>>>)运算符可以将所有的位向右移动,同时用零填充移动过的值。这也称为无符号右移运算符。>>>运算符按照指定的次数移动位,语法如下:

value or expression >>> num

在该语法中,num指定了要执行右移操作的次数,val或expression指定了操作数。

例如:

int a = 10;
int b = a>>>2;

操作过程如下:

00001010  //10所对应的二进制位

当>>>运算符对操作数执行第一次操作时,会丢失最右侧的位(0),其他所有的位向右移动,同时用0填充最左侧的位。在此之后形成的位模式如下:

00000101  //8所对应的二进制位

在第二步中,重复与第一步相同的过程,最后形成的位模式如下:

00000010  //4所对应的二进制位


 提示

右移(>>)和零填充右移(>>>)运算符之间的差异在于符号扩展。零填充右移运算符>>>将零填充到最左侧位置,而在右移(>>)中最左侧位置取决于符号扩展。


示例2-7

下面的程序将执行所有的按位操作并在屏幕上显示结果。

//编写程序,执行各种按位操作
1   class BitwiseOp_demo
2   {
3      public static void main(String args[])
4      {
5          int a = 15, b = 10, c = 0;
6          c = a & b;      /* 10 = 0000 1010 */
7          System.out.println("a & b = " + c );
8          c = a | b;      /* 15 = 0000 1111 */
9          System.out.println("a | b = " + c );
10         c = a ^ b;      /* 5 = 0000 0101 */
11         System.out.println("a ^ b = " + c );
12         c = ~a;         /*-16 = 1111 0000 */
13         System.out.println("~a = " + c );
14         c = a << 2;     /* 60 = 0011 1100 */
15         System.out.println("a << 2 = " + c );
16         c = a >> 2;     /* 3 = 0000 0011 */
17         System.out.println("a >> 2 = " + c );
18         c = a >>> 2;    /* 3 = 0000 1111 */
19         System.out.println("a >>> 2 = " + c );
20     }
21  }

讲解

第5行

int a = 15, b = 10, c = 0;

在该行中,a、b、c被声明为整数类型变量并分别被初始化为15、10、0。

第6行

c = a & b;

在该行中,运算符&对变量a和b执行按位AND操作并将结果赋给变量c。

第7行

System.out.println("a & b = " + c );

该行会在屏幕上显示下列内容:

a & b = 10

第8行

c = a | b;

在该行中,运算符|对变量a和b执行按位OR操作并将结果赋给变量c。

第9行

System.out.println("a | b = " + c );

该行会在屏幕上显示下列内容:

a | b = 15

第10行

c = a ^ b;

在该行中,运算符^对变量a和b执行按位XOR操作并将结果赋给变量c。

第11行

System.out.println("a ^ b = " + c );

该行会在屏幕上显示下列内容:

a ^ b = 5

第12行

c = ~a;

在该行中,运算符^对变量a和b执行按位XOR操作并将结果赋给变量c。

第13行

System.out.println("~a = " + c );

该行会在屏幕上显示下列内容:

~a = -16

第14行

c = a << 2;

在该行中,按位左移运算符<<将变量a的所有位向左移动2位。在这个过程中,最左侧的位会丢失,最终的结果被赋给变量c。

第15行

System.out.println("a << 2 = " + c );

该行会在屏幕上显示下列内容:

a << 2 = 60

第16行

c = a >> 2;

在该行中,按位右移运算符>>将变量a的所有位向右移动2位。在这个过程中,最右侧的位会丢失,最终的结果被赋给变量c。

第17行

System.out.println("a >> 2 = " + c );

该行会在屏幕上显示下列内容:

a >> 2 = 3

第18行

c = a >>> 2;

在该行中,按位零填充右移运算符>>将变量a的所有位向右移动2位。移动过的值用零填充,最终的结果被赋给变量c。

第19行

System.out.println("a >>> 2 = " + c );

该行会在屏幕上显示下列内容:

a >>> 2 = 3

示例2-7的输出如图2-7所示。

图2-7 示例2-7的输出

关系运算符可以决定两个表达式之间的关系。这类运算符基本上用于比较两个值,其结果是一个布尔值——ture或false。表2-8给出了关系运算符清单及其语法。

表2-8 关系运算符及其语法

运算符

操作

语法

==

等于

var1==var2

!=

不等于

var1!=var2

>

大于

var1>var2

<

小于

var1<var2

>=

大于或等于

var1>=var2

<=

小于或等于

var1<=var2

在表2-8所示的语法中,关系运算符用于检查两个变量var1和var2之间的关系。如果变量var1和var2的值满足条件,则此操作的结果为ture;否则,结果为false。

因为关系运算符多用于流程控制语句,所以关于关系运算符更多的用法可参见第3章。

通过第2.8.4节的学习,我们知道了关系运算符用于比较两个表达式或处理某种条件。但有时候,我们可能需要在一条语句中比较两个或多个条件。为此,Java提供了另一组运算符——逻辑运算符。逻辑运算符用于一次比较两个或多个关系表达式(包含关系运算符的语句),这些运算符的结果是布尔值——true或false。表2-9给出了逻辑运算符清单。

表2-9 逻辑运算符

运算符

操作

&&

逻辑短路AND运算符

||

逻辑短路OR运算符

!

逻辑NOT运算符

其中,逻辑NOT(!)运算符的操作形式与单目求补运算符一样,用于将布尔值从false反转为true或从true反转为false。

例如:

!(x == y)

在这个例子中,运算符==(等于)用于检查两个值(x和y)之间的相等性。如果关系表达式(x == y)的结果为true,那么该结果会被逻辑NOT运算符反转。因此,最终的结果就是false。

(1)逻辑短路AND(&&)与OR(||)运算符

短路运算符&&和||多用于流程控制语句,其最终结果取决于两个或更多的结果。如果所有的操作数都为true,运算符&&返回true;否则,返回false。如果其中某个操作数为true,运算符||返回true;否则,返回false。表2-10显示了短路运算符&&和||的操作方式。

表2-10 短路运算符

X Y X && Y X||Y
false false false false
false true false true
true false false true
true true true true

在表2-10中,只有当两个操作数都为true时,运算符&&才返回true;否则,返回false。对于运算符||而言,只要其中一个操作数为真,就返回true。这些运算符称为短路运算符(short-circuit operators)的原因在于,使用的时候只对左侧的操作数求值。根据该操作数的结果得到最终结果。在第3章中我们将学习更多有关逻辑运算符的内容。

该行会在屏幕上显示下列内容:

赋值运算符用于为变量分配值。这类运算符可分为两类。

1.简单赋值运算符

简单赋值运算符由等号(=)表示,用于为变量分配值。在本章先前的例子中对其已经有过讨论。赋值运算符的语法如下:

variable_name = value;

在该语法中,赋值运算符(=)右侧的value被分配给左侧的variable_name。这种位置上的安排是固定不变的。赋值运算符右侧的value可以是变量、常量或操作结果。

我们也可以使用赋值运算符完成多个赋值操作,语法如下:

var1 = var2 = var3 = value;

在该语法中,由value所描述的同一个值被赋给所有var1、var2、var3共3个变量。赋值操作从右向左求值,因此在上面的语句中,值先赋给var3,var3然后赋给var2,var2最后赋给var1。

2.复合赋值运算符

复合赋值运算符是两种运算符的组合:第一个指定要执行的运算,第二个是赋值运算符。复合赋值运算符也称为便写赋值运算符(short hand assignment operators)。表2-11显示了复合赋值运算符及其语法。

表2-11 复合赋值运算符及其语法

运算符

描述

语法

等价表达式

+=

将左侧的操作数与右侧的操作数相加,然后将结果赋给左侧的操作数

var1+=var2;

var1=var1+var2;

−=

将左侧的操作数与右侧的操作数相减,然后将结果赋给左侧的操作数

var1−=var2;

var1=var1−var2;

*=

将左侧的操作数与右侧的操作数相乘,然后将结果赋给左侧的操作数

var1*=var2;

var1=var1*var2;

/=

将左侧的操作数与右侧的操作数相除,然后将结果赋给左侧的操作数

var1/=var2;

var1=var1/var2;

%=

对左侧的操作数与右侧的操作数求模,然后将结果赋给左侧的操作数

var1%=var2;

var1=var1%var2;

&=

按位AND赋值运算符

var1&=var2;

var1=var1&var2;

|=

按位OR赋值运算符

var1|=var2;

var1=var1|var2;

^=

按位XOR赋值运算符

var1^=var2;

var1=var1^var2;

<<=

按位左移赋值运算符

var1<<=2;

var1=var1<<2;

>>=

按位右移赋值运算符

var1>>=2;

var1=var1>>2;

>>>=

按位零填充右移赋值运算符

var1>>>=2;

var1=var1>>>2;

在表2-11显示的语法中,第一个指定的操作在变量var1和var2上执行,然后将操作结果再赋给var1。

例如,要给变量a加4,然后把结果再赋给变量a,写法如下:

a+=4;

我们也可以使用下面的语句执行相同的操作:

a = a + 4 ;

示例2-8

下面的程序将对指定的值执行复合赋值操作并在屏幕上显示结果。

//编写程序,执行赋值操作
1   class Assign_demo
2   {
3      public static void main(String args[])
4      {
5         int var = 10, result = 0;
6         result += var; //10
7         System.out.println("result += var : " + result );
8         result *= var; //100
9         System.out.println("result *= var : " + result );
10        result -= var; //90
11        System.out.println("result -= var : " + result );
12        result /= var; //9
13        System.out.println("result /= var : " + result );
14        result %= var; //9
15        System.out.println("result %= var : " + result );
16        result ^= var; //3
17        System.out.println("result ^= var = " + result );
18        result |= var; //11
19        System.out.println("result |= var = " + result );
20        result &= var; //10
21        System.out.println("result &= var = " + result );
22        result <<= 2;  //40
23        System.out.println("result <<= 2 = " + result );
24        result >>= 2;  //10
25        System.out.println("result >>= 2 = " + result );
26        result >>>= 3; //1
27        System.out.println("result >>>= 3 = " + result );
28     }
29  }

讲解

第5行

int var = 10, result = 0;

在该行中,var和result被声明为整数类型变量并分别被初始化为10和0。

第6行

result += var;

在该行中,变量result的值(0)先与变量var的值(10)相加,然后将结果分配给变量result。

第7行

System.out.println("result += var : " + result );

result += var : 10

第8行

result *= var;

在该行中,变量result的值(10)先与变量var的值(10)相加,然后将结果分配给变量result。

第9行

System.out.println("result *= var : " + result );

该行会在屏幕上显示下列内容:

result *= var : 100

第10行

result -= var;

在该行中,变量result的值(100)先减去变量var的值(10),然后将结果分配给变量result。

第11行

System.out.println("result -= var : " + result );

该行会在屏幕上显示下列内容:

result -= var : 90

第12行

result /= var;

在该行中,变量result的值(90)先除以变量var的值(10),然后将结果(商)分配给变量result。

第13行

System.out.println("result /= var : " + result );

该行会在屏幕上显示下列内容:

result /= var : 9

第14行

result %= var;

在该行中,变量result的值(9)先与变量var的值(10)求模,然后将结果(余数)分配给变量result。

第15行

System.out.println("result %= var : " + result );

该行会在屏幕上显示下列内容:

result %= var : 9

第16行

result ^= var;

在该行中,先对值分别为9和10的变量result和var执行按位XOR运算,然后将结果分配给变量result。

第17行

System.out.println("result ^= var = " + result );

该行会在屏幕上显示下列内容:

result ^= var = 3

第18行

result |= var;

在该行中,先对值分别为3和10的变量result和var执行按位OR运算,然后将结果分配给变量result。

第19行

System.out.println("result |= var = " + result );

该行会在屏幕上显示下列内容:

result |= var = 11

第20行

result &= var;

在该行中,先对值分别为11和3的变量result和var执行按位AND运算,然后将结果分配给变量result。

第21行

System.out.println("result &= var = " + result );

该行会在屏幕上显示下列内容:

result &= var = 10

第22行

result <<= 2;

在该行中,先对值为10的变量result执行按位左移运算。result的所有位都向左移动2位,最左侧的位会因此而丢失。然后,将结果分配给变量result。

第23行

System.out.println("result <<= 2 = " + result );

该行会在屏幕上显示下列内容:

result <<= 2 = 40

第24行

result >>= 2;

在该行中,先对值为40的变量result执行按位右移运算。result的所有位都向右移动3位,最右侧的位会因此而丢失。然后,将结果分配给变量result。

第25行

System.out.println("result >>= 2 = " + result );

该行会在屏幕上显示下列内容:

result >>= 2 = 10

第26行

result >>>= 3;

在该行中,先对值为10的变量result执行按位零填充右移运算。result的所有位都向右移动2位,移动后的值以零填充。然后,将结果分配给变量result。

第27行

System.out.println("result >>>= 3 = " + result );

该行会在屏幕上显示下列内容:

result >>>= 3 = 1

示例2-8的输出如图2-8所示。

图2-8 示例2-8的输出

?:运算符也称为三目运算符,因为其使用了3个操作数。第一个操作数是布尔表达式。如果表达式为true,则返回第二个操作数,否则返回第三个操作数。它是一个条件运算符,比if-else语句的语法(在随后的章节中讨论)更简短。?:运算符的语法如下:

conditional_expression ? statement 1 : statement 2

在该语法中,如果conditional_expression指定的条件为ture,则执行statement 1;否则,执行statement 2。

例如:

int c = a!=0 ? a : b;

在这个例子中,先评估条件表达式a!=0(变量a的值不等于0)。如果条件为true,则将变量a的值赋给整数类型变量c;否则,将变量b的值赋给整数类型变量c。

示例2-9

下面的程序使用?:运算符查找指定的两个数字中的较大者并将其赋给另一个变量,然后在屏幕上显示结果。

//编写程序,查找较大的数字
1   class Ternary_demo
2   {
3         public static void main(String arg[])
4         {
5               int a=20, b=11, c;
6               c= a>b ? a : b;
7               System.out.println("The greater value is: " +c);
8         }
9   }

讲解

第6行

c= a>b ? a : b;

该行中用到了?:运算符。首先,评估条件表达式a>b。因为变量a的值(20)大于变量b的值(11),所以该条件为true。现在,变量a的值就被赋给了变量c。

第7行

System.out.println("The greater value is: " +c);

该行会在屏幕上显示下列内容:

The greater value is: 20

示例2-9的输出如图2-9所示。

图2-9 示例2-9的输出

instanceof运算符用于在运行时检查对象是否为指定类型(类、子类或接口)的实例。该运算符也称为类型比较运算符(type comparison operator),因为它会比较实例和类型。如果对象为指定类型,则instanceof运算符返回true;否则,返回false。如果将其应用于值为空的任何变量,返回false。

instanceof运算符的语法如下:

object_name instanceof class_name

示例2-10

下面的程序使用instanceof运算符检查对象是否为指定类的实例并在屏幕上显示结果。

//编写程序,检查对象是否为指定类的实例
1   class Instanceof_demo
2   {
3      public static void main(String args[])
4      {
5         Instanceof_demo id=new Instanceof_demo();
6         boolean i=id instanceof Instanceof_demo;
7         System.out.println( "value:" +i);
8      }
9   }

讲解

第5行

Instanceof_demo id=new Instanceof_demo();

在该行中,创建了Instanceof_demo类的对象id。

第6行

boolean i=id instanceof Instanceof_demo;

在该行中,使用instanceof运算符检查对象id是否为Instanceof_demo类的实例。

第7行

System.out.println( "value:" +i);

该行会在屏幕上显示下列内容:

value: true

示例2-10的输出如图2-10所示。

图2-10 示例2-10的输出

运算符优先级决定了编译器执行运算符的顺序。高优先级的运算符先于低优先级的运算符执行。

除赋值运算符之外的所有双目运算符都从左到右求值。当相同优先级的运算符出现在同一表达式中时,其求值顺序为从左到右,而赋值运算符则是从右到左求值。

表2-12按照优先级从高到低的顺序给出了Java运算符的清单。

表2-12 运算符优先级

优先级

运算符

1

()  []  .

2

++var  − −var  +var  −var  ~var  !var

3

*  /  %

4

+  −

5

<<  >>  >>>

6

>  <  <=  >=  instanceof

7

==  !=

8

&

9

^

10

|

11

&&

12

||

13

?:

14

=  +=  −=  *=  /=  %=  &=  ^=  |=  <<=  >>=  >>>=


 提示

在表2-12中,1代表最高优先级,14代表最低优先级。在同一行中出现的运算符具有相同的优先级。


例如:

x=a+b*c

乘法运算符(*)的优先级高于加法运算符(+)和赋值运算符(=)。因此,在上面的例子中,变量b的值先乘以变量c的值,然后将结果与变量a的值相加(因为加法运算符的优先级高于赋值运算符)。最后,将表达式a+b*c的结果赋给变量x。

迄今为止我们讲解过的所有示例中,在执行期间都没有向程序传递任何信息。但有时候,我们的确需要在程序执行期间传入信息。这可以通过命令行参数来实现。只需把参数放在待执行的程序名称之后就可以将其在程序运行期间传入。这些命令行参数会被保存在main()方法的String类型的arg[ ]数组之中。

例如:

D:\Java Projects\Ch02>java demo How are you

在这个例子中,demo是程序名称,How are you是命令行参数。其中,第一个参数How被保存在arg[0],are被保存在arg[1],以此类推。

示例2-11

下面的程序演示了命令行参数的用法。该程序会显示出用户输入的所有命令行参数。

//编写程序,显示所有的命令行参数
1   class Commandline_demo      
2   {
3      public static void main(String arg[])  
4      {         
5          System.out.println("First argument is: " +arg[0]
6          System.out.println("Second argument is: " +arg[1] 
7      }
8   }

讲解

这个例子中,在程序运行期间传入的参数位于arg[]数组索引为0和1的位置上。

使用下列命令执行该程序:

java Commandline_demo Hello User

示例2-11的输出如图2-11所示。

图2-11 示例2-11的输出

通过命令行参数只能传入String类型的值,这是因为arg[]数组是String类型的。如果希望传入其他类型,则需要进行类型转换。实现类型转换的方法有多种,接下来我们将对其展开讨论。

在Java中,我们可以使用Integer.parseInt()方法将String类型转换为int类型。只要用户希望执行数学运算,就必须用到数字。但是将数字传入程序的时候,JVM会将其视为String类型。在这种情况下,用户需要使用Integer.parseInt()方法将值从String类型转换为int类型。

例如:

int x = Integer.parseInt(arg[0]);

在这个例子中,parseInt是Integer类的方法,可用于从命令行参数中读取数值。然后,将结果赋给int类型变量x。

我们可以使用Long.parseLong()方法将String类型转换为long类型。只要用户希望使用 long类型的数值执行数学运算,就必须用到该方法。

例如:

long y = Long.parseLong(arg[0]);

在这个例子中,parseLong是Long类的方法,可用于从命令行参数中读取long类型的数值。然后,将结果赋给long类型变量y。

我们可以使用Float.parseFloat()方法将String类型转换为float类型。只要用户希望使用float类型的数值执行数学运算,就必须用到该方法。

例如:

float z = Float.parseFloat(arg[0]);

在这个例子中,parseFloat是Float类的方法,可用于从命令行参数中读取float类型的数值。然后,将结果赋给float类型变量z。

示例2-12

下面的程序演示了将命令行参数由String类型转换成int类型的做法。该程序计算用户输入的两个整数之和并将结果显示在屏幕上。

//编写程序来计算用户输入的两个整数的和
1   class Command_demo
2   {
3      public static void main(String arg[])
4      {
5         int a,b,c;
6         a= Integer.parseInt(arg[0]);
7         b= Integer.parseInt(arg[1]);
8         c=a+b;
9         System.out.println("Addition = " +c);
10     }
11  }

讲解

第6行和第7行

int a = Integer.parseInt(arg[0]);

int b = Integer.parseInt(arg[1]);

在这两行中,Integer类的parseInt方法用来从命令行参数中读取数值。然后,将结果分别赋给整数类型变量a和b。

示例2-12的输出如图2-12所示。

图2-12 示例2-12的输出

回答以下问题,然后将其与本章末尾给出的问题答案比对。

1.______是具名的存储位置,可以在其中保存数据。

2.在类内部(但是在方法外部)声明的变量称为______变量。

3.______转换用于将较大的数据类型转换成较小的数据类型。

4.______运算符可以返回两个数的余数。

5.______运算符用于将操作数的值加1。

6.在Java中,所有原始类型的大小都是明确定义的。(对/错)

7.变量名能够以数字开头。(对/错)

8.在Java中,+号的作用是拼接。(对/错)

9.在Java中,类变量是通过static关键字声明的。(对/错)

10.%运算符可以返回两个数的商。(对/错)

回答下列问题。

1.局部变量与实例变量之间的差异。

2.使用适合的例子解释显式类型转换。

3.使用适合的例子解释%运算符的作用。

4.使用适合的例子解释前缀递增运算符的作用。

5.使用适合的例子解释?:运算符。

6.解释instanceof运算符。

7.原始类型与用户自定义类型之间的差异。

8.找出下列程序语句中的错误:

 (a)class Demo
       {
           public static main void(String args[])
           {
               System.out.println("Hello Java");
           }
       }
 (b)class Variable_demo
       {
           public static void main(String args[])
           {
               int a =10, b=19;
               c=a+b;
               System.out.println(c);
           }
       }
 (c)class Type_convert
       {
           public static void main(String args[])
           {
               byte a;
               int b = 200;
               a = b;
               ----------;
               ----------;
           }
       }
 (d)Class Syntax
       {
           public static void main(String args[])
           {
               System.out.println("Error");
           }
       }
 (e)class Ternary
       {
           public static void main(String args[])
           {
               int x= 10, y=10, c;
               c= x==y ? x : y;
               ----------;
               ----------;
           }
       }

练习1

编写程序,使用右移运算符>>将数值200向右移动两位。

练习2

编写程序,计算圆的面积,其中半径由用户来输入。

 

 

 

自我评估测试答案

1.variable 2.instance 3.explicit 4.% 5.++ 6.对 7.错 8.对 9.对 10.错

[1] 准确地说,保存的是Unicode字符集中字符的codepoint(码值)。

[2] 严格来说,type conversion与type casting并非同义词。


相关图书

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)

相关文章

相关课程