Java从入门到精通(微视频精编版)
上QQ阅读APP看书,第一时间看更新

第3章 Java语言基础知识

视频讲解:2小时27分钟

很多人认为学习Java语言之前必须要学习C++语言,其实并非如此,这种错误的认识是因为很多人在学习Java语言之前都学过C++语言,事实上Java语言要比C++语言更容易掌握。要掌握并熟练应用Java语言,就需要对Java语言的基础进行充分的了解。本堂课对Java语言基础进行了比较详细的介绍,对于初学者来说应该对本堂课的各个小节进行详细的阅读、思考,才能达到事半功倍的效果。

学习摘要:

 Java主类结构

 基本数据类型

 常量与变量

 各种运算符的使用

 数据类型的转换

 代码注释与编码规范

3.1 Java主类结构

视频讲解

Java语言是面向对象的程序设计语言,Java程序的基本组成单元就是类,类体中又可包括属性与方法两部分。每一个Java本地应用程序都必须包含一个main()方法,含有main()方法的类称之为主类。下面通过程序来介绍Java主类结构。

【例3.1】 创建包myclass.struct,创建类Frist。在类体中输入如下代码,实现在控制台上输出“让我看看,主类的结构。”文本内容。(实例位置:资源包\源码\03\3.01)

运行结果如图3.1所示。

图3.1 实例运行结果

3.1.1 定义类包

第1行语句package myclass.struct;用于声明First类所在的包。package为声明包的关键字。使用包可以分类存储不同的Java类,使代码更加方便管理,本书将在第6章对包进行讲解。

3.1.2 定义类

一个Java应用程序是由若干个类组成的。第3行代码就声明了一个类Java类,它是本堂课的第一个类,所以取名为First。

3.1.3 导入API类库

Java类必须执行导入才能够被当前类使用。在Java语言中可以通过import关键字导入相关的类。

注意

Java语言是严格区分大小写的。例如:关键字class不等于Class,同理First与first是两个不同的Java类。

3.1.4 定义变量

通常将类的属性称之为类的全局变量(或成员变量)。将方法中的属性称之为局部变量。全局变量声明在类体当中,局部变量声明在方法体当中。全局变量和局部变量都有各自的应用范围。第4行代码定义的s1是成员变量,而第7行代码定义的s2是局部变量。

3.1.5 定义主方法

main()方法是类体中的主方法。该方法从“{”号开始,至“}”号结束,中间的是方法体。public、static、void分别是main()方法的权限修饰符、静态修饰符和返回值类型声明,在Java程序中的main()方法,必须声明为public static void。String arg[]是一个字符串类型的数组,它是main()方法的参数。main()方法是程序开始执行的位置。

说明

main()方法是程序入口方法。它有固定的格式,方法的参数也固定为一个字符串数组。现在,读者只要记住主方法的格式即可。在本书的基础章节,所有实例都比较简单,所以基本上都是在main()方法上运行的。

3.1.6 运行主类

Java类需要经过编译成“.class”后缀的二进制字节码文件,然后才能够运行,在Eclipse开发工具中,编译步骤是自动的,我们可以直接运行主类程序。方法是:在“包资源管理器”视图中找到要运行的类文件(该类必须包含main()方法),在文件上右击,在弹出菜单中选择“运行方式”→“ Java应用程序”命令。

3.2 代码注释

视频讲解

通过在程序代码中添加注释可提高程序的可读性。在Java源程序文件的任意位置都可添加注释语句。注释中的文字Java编译器并不进行编译,所有代码中的注释文字并不对程序产生任何影响。Java语言提供了3种添加注释的方法。分别为:单行注释、多行注释和文档注释。

3.2.1 单行注释

“//”为单行注释标记,从符号“//”开始直到换行为止的所有内容均作为注释而被编译器忽略,语法如下。

// 注释内容

例如以下代码为声明的int型变量添加注释。

3.2.2 多行注释

“/* */”为多行注释标记,符号“/*”与“*/”之间的所有内容均为注释内容。注释当中的内容可以换行,语法如下。

/*
注释内容1
注释内容2
…
*/

3.2.3 JavaDoc文档注释

“/**”与“*/”是文档注释的起始和结束标记。符号“/**”与“*/”之间的内容均为文档注释内容。当文档注释出现在任何声明(如类的声明、类的成员变量的声明、类的成员方法声明等)之前时,会被JavaDoc文档工具读取作为JavaDoc文档内容。文档注释的格式与多行注释的格式相同。对与初学者,文档注释了解即可。例如,为First类的主方法添加文档注释的关键代码如下。

添加了文档注释的类成员,会在Eclipse的JavaDoc视图中显示相应的说明,另外,在编辑器中,把鼠标停留在main()方法或引用main()方法的位置上,也会出现悬浮提示信息,如图3.2所示。

图3.2 类成员文档注释信息

技巧

在Java源文件编辑器中,选择某个成员方法或成员变量,然后按Alt+Shift+J快捷键,Eclipse会自动添加JavaDoc文档注释结构,如果是方法的话,还会自动添加参数名称。

3.3 变量与常量

视频讲解

在程序执行过程中,其值不能改变的量称为常量。其值能被改变的量称为变量。变量与常量的命名都要必须使用合法的标识符。本节将向读者介绍标识符与关键字,以及变量与常量的命名。

3.3.1 Java保留字

1.标识符

标识符可以简单地理解为一个名字,用来标识类名、接口、标签、变量名、方法名的有效字符序列。

Java语言规定标识符由任意顺序的字母、下画线(_)、美元符号($)和数字组成,并且第一个字符不能是数字。不能是Java中的保留关键字。

下面是合法标识符。

name
user_age
$page

下面是非法标识符。

在Java语言中标识符中的字母是严格区分大小写的。如good和Good是不同的两个标识符。Java语言使用unicode标准字符集,最多可以标识65535个字符,因此,Java语言中的字母不仅包括通常的拉丁文字a、b、c等,还包括汉字、日文以及其他许多语言中的文字。

2.关键字

关键字是Java语言中已经被赋予特定意义的一些单词。不可以把这些字作为标识符来使用。上节介绍的数据类型中提到的int、boolean等都是关键字,Java中的关键字如表3.1所示。

表3.1 Java关键字

3.3.2 定义变量

变量可以理解为日常生活中的一个容器,例如箱子,它可以装衣服、金银首饰、图书、旅行用品等,关键时刻还可以藏人,总之变量的内容是可以改变的。变量的使用是程序设计中一个十分重要的环节。

为什么要定义变量呢?简单地说,就是要告诉编译器(compiler)这个变量是属于哪一种数据类型,这样编译器才知道需要配置多少空间给它,以及它能存放什么样的数据。在程序运行过程中,空间内的值是变化的,所以称为变量。为了便于操作,给这个空间取个名字,称为变量名,内存空间内的值就是变量值。变量的命名必须是合法的标识符。在声明变量时可以不赋值,也可以是直接赋给初值。例如:

当编写以上程序代码,究竟会产生什么样的作用呢?要了解这个问题,就需要对变量的内存配置有一定的认识。笔者用图解的方式,将上例程序代码在内存中的状况表现出来,如图3.3所示。

图3.3 变量占用的内存空间

由图3.3可知,系统的内存可大略分为3个区域:系统区(OS)、程序区(Program)、数据区(Data)。当程序执行时,程序代码会加载到内存中的程序区,数据暂时存储在数据区中。对于变量的命名并不是任意的,应遵循以下几条规则。

 变量名必须是一个有效的标识符。

 变量名不可以使用Java中的关键字。

 变量名不能重复,在其作用范围内必须是唯一的。

 应选择有意义的单词作为变量名,做到见其名知其意。

说明

在Java语言中允许使用汉字或其他语言文字作为变量名。如“int年龄 = 21”,在程序运行时并不出现什么错误,但建议读者尽量不要使用这些语言文字作为变量名。

3.3.3 定义常量

常量是不能被改变的量,它和变量的性质完全相反。Java使用关键字final来声明常量,并且常量在声明之后,只能够初始化一次。

语法:final数据类型 常量名称[=值]

参数:常量名通常使用大写字母,这也符合Java编码规范,但这并不是必须的,声明常量时,完全可以和变量名一样使用小写字母。但是,那样容易造成混淆,降低代码可读性,所以才有规范要求常量名全部大写,并使用下画线(_)字符分割多个单词。例如:

全局常量(或成员常量)被声明之后,必须马上初始化,或者在类的所有构造方法中进行初始化。否则编译器会报错。

3.3.4 常量与变量的有效范围

变量被声明与初始化之后,只是暂存在内存中,当变量不再被程序使用时,将被销毁并释放所占用的内存空间,即变量有它的生命周期。每个变量的生命长短和它的有效范围息息相关,所谓有效范围就是变量在程序中起作用的区域,若超出该区域则无法访问该变量。变量根据有效范围的不同分为全局变量和局部变量。

1.全局变量

根据变量有效范围、类型和所有者的不同,变量又有以下几种不同的分类。

全局变量又称为成员变量,定义在类体中,它的有效范围是整个类的代码段。也就是在类体中的任何位置都可以使用该变量。例如:

全局变量num和price在method1()方法中被重新赋值,在method2()方法中也同样可以被访问。

2.局部变量

在方法体中定义的变量就是一种局部变量,局部变量只在当前代码块(即大括号之内)中有效。局部变量的生命周期取决于声明位置的代码块,超出这个代码块的范围就不能再使用代码块内的局部变量。

就拿方法类说,方法内声明的变量、包括参数变量都属于局部变量,当方法被调用时,Java虚拟机为方法中的局部变量分配内存空间,当该方法的调用结束后,则会释放方法中局部变量占用的内存空间,局部变量也将会销毁,然后Java的垃圾回收机制会在某一时刻清理该内存空间。

局部变量可与全局变量的名字相同,此时全局变量将被隐藏,但是可以使用“this.”做前缀来访问全局变量。

【例3.2】 在项目中创建类Val,分别定义名称相同的局部变量与全局变量,当名称相同时成员变量将被隐藏。(实例位置:资源包\源码\03\3.02)

运行结果如图3.4所示。

图3.4 实例运行结果

3.4 数据类型

视频讲解

Java的数据类型分为基本数据类型和对象引用类型。在介绍面向对象知识之前,我们先来介绍基本数据类型。在Java中有8种基本数据类型来存储数值、字符和布尔值。

3.4.1 计算机常用数制

现在的计算机功能丰富、性能优越,可以听歌、看电影、图像处理、进行3D游戏等。但它终究是一个电子产品,这些丰富的资源存储在计算机中只能使用“0”和“1”组成的数字表示,它们对应着电子晶体管的“关”和“开”状态,即所谓的二进制。例如数字“128”在计算机中的二进制表现形式为“10000000”,一个非常简单的数字存储到计算机中就变得非常烦琐、难以计算。所以又出现了八进制与十六进制,另外,在现实社会中,使用最多的是十进制,例如重量、价格、年龄,这些都使用十进制表示。而程序需要人来编写,所以,为迎合人类的计数习惯,几乎所有高级程序设计语言中的数值都以十进制作为默认数制。本节将介绍几种常用的数制。

1.十进制

十进制就是“逢十进一”,这是我们最熟悉的进制,当我们去商场购物时,对货币的计算都要使用十进制进行计算,9元钱加上1元钱,就是10元钱,这就是“逢十进一”,进位后就成了10。

2.二进制

所谓二进制就是“逢二进一”,它的字面量只包含0和1,在二进制的预算法则中,1+1不再等于2,而是等于10,二进制的10与十进制的2相等。

3.八进制

八进制的最大单个数字是7,7再加1就是10,八进制的10和十进制的8相等。八进制的字面量包括“0、1、2、3、4、5、6、7”。

4.十六进制

十六进制主要用于二进制的简化表达方式,十六进制的1位数字可以转换成4位二进制数字。超出9的数字在十六进制中以字母表示,其字面量包括“0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F”,其中“A~F”分别代码十进制的“10~15”。

常用进制的字面量对比如表3.2所示。

表3.2 进制转换表

技巧

可以使用Windows系统的计算器方便的转换不同进制之间的数值。单击“开始”→“所有程序”→“附件”→“计算机”启动它,然后在计算机的菜单栏选择“查看”→“程序员”,然后可以输入要转换的指定进制的数值,再单击要转换的目标数制便可。如图3.5所示是十六进制的“F1B0”转换成二进制的结果。

图3.5 利用计算机转换数制

3.4.2 整数类型

整数类型用来存储整数数值,即没有小数部分的数值。可以是正数也可以是负数。整型常量在Java程序中有3种表示形式,分别为十进制、八进制和十六进制。

十进制是Java语言默认的数制,所以使用正常的表示形式。例如:

120、0、-127、340

注意

不能以0作为十进制数的开头(0除外)。

八进制的表现形式以最高位的数字0做区分,如果最高位不是0,那么Java将把它解释为十进制,否则解释为八进制。例如:

注意

八进制必须以0开头。

十六进制的表现形式是在数制最高位添加0x标识,其中x字符不区分大小写。例如:

注意

十六进制必须以0X或0x开头。

整型变量根据它在内存中所占大小的不同,可分为byte、short、int和long 4种类型。它们具有不同的取值范围,如表3.3所示。

表3.3 整型数据类型

为这4种整数类型变量赋值时,要注意变量能够接受的最大值与最小值,否则会出现错误。Java默认的整数类型是int,如果要标记整数是long类型,必须在数字末尾添加字母“L”。例如long num =2147483650L。

说明

在数字末尾添加“L”,标识long类型整数的情况一般都发生在整数大于int最大取值范围的时候。因为Java默认的整数类型是int。

【例3.3】 在项目中创建类Integer,在主方法中创建不同数值型变量,并将这些变量相加,将和输出。(实例位置:资源包\源码\03\3.03)

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

图3.6 实例运行结果

3.4.3 浮点类型

Java语言中浮点类型分为单精度浮点类型(float)和双精度浮点类型(double)。它们具有不同的取值范围,如表3.4所示。

表3.4 浮点型数据类型

Java语言默认使用double双精度类型的浮点数,就像int是默认的整数类型一样。如果将实数数赋值给float类型的变量,则需要在实数末尾添加字母F做后缀;否则被认为是double类型数值。例如:

可以使用后缀d或D来明确表明这是一个double类型数据。但加不加d没有硬性规定,可以加也可以不加。而声明float型变量时如果不加F,编译器会认为是double类型而出错。

3.4.4 字符类型

1.char型

字符类型(char)用于存储单个字符,占用16位(两个字节)的内存空间。字符类型的字面量以单引号表示,例如's'表示一个字符。而"s"则表示一个字符串,虽然其只有一个字符,但由于使用双引号,所以它仍然表示字符串,而不是字符。使用char关键字可定义字符变量。例如:

char x = 'a';

字符类型与整数类型可以互相赋值,也就是可以把整数赋值给字符变量,也可以把字符变量赋值给整数类型变量。由于字符a在unicode表中的编码是97。因此,允许将上面的语句写成如下。

char x = 97;

同C、C++语言一样,Java语言也可以把字符作为整数对待。由于unicode编码采用无符号编码,可以存储65536个字符(0x0000~0xffff),所以Java中的字符几乎可以处理所有国家的语言文字。若想得到一个0~65536的数所代表的unicode表中的相应编码的字符也必须使用char型显示转化。

【例3.4】 在项目中创建类CharAndInt,在主方法中编写如下代码,演示字符类型与整数类型的通用赋值方式,关键代码如下。(实例位置:资源包\源码\03\3.04)

运行结果如图3.7所示。

图3.7 实例运行结果

2.转义字符

转义字符是一种特殊的字符变量。转义字符以反斜线“\”开头,后跟一个或多个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”。例如“\n”就是一个转义字符,意思是“回车换行”,Java中转义字符如表3.5所示。

表3.5 转义字符表

将转义字符赋值给字符变量时,与字符常量值一样需要使用单引号。例如:

【例3.5】 在类的主方法中使用转义字符完成控制台字符串输出,主方法的关键代码如下。(实例位置:资源包\源码\03\3.05)

实例运行结果如图3.8所示。

图3.8 实例运行结果

3.4.5 布尔类型

布尔类型又称逻辑类型,只有两个值true和false,分别代表布尔逻辑中的“真”和“假”,布尔值不能与整数类型进行转换。布尔类型通常被用在流程控制中作为判断条件。

通过关键字boolean定义布尔类型变量。例如:

3.5 数据类型转换

视频讲解

数据类型转换就是把数据的类型转变为另一种类型。例如,可以将long类型数据“457”转换为一个int整数类型。Java对数据类型的转换有严格的规定,数据从占用存储空间较小的类型转换为占用存储空间较大的数据类型时,不用做显示的类型转换(即自动类型转换);反之则必须做强制类型转换。

3.5.1 自动类型转换

Java的8个基本数据类型可以进行混合运算。不同类型的数据在运算过程中,首先会自动转换为同一类型,然后才进行运算。数据类型可以根据占用存储空间大小分为高低级别,占用空间越小,级别越低,占用空间越大,级别越高。自动类型转换遵循低级到高级转换的规则。如图3.9所示。从左到右的数据类型不断升高,箭头指明了自动类型转换的规则。

图3.9 数据类型级别与自动转换规则

基本数据类型的自动类型转换会发生在以下几种情况。

 变量赋值

当为变量赋值的数据类型与变量类型不一致,并且赋值的数据类型级别低于变量类型的级别时,自动数据类型转换会将赋值数据自动转换为变量的类型。例如:

 方法调用

把一个数值传递给方法的参数,并且这个数值的数据类型低于方法的参数变量的数据类型。例如:

 一元运算

在一元运算中(除了++和−运算符),如果操作数的类型低于int类型(即byte、short和char类型),则操作数会自动转换为int类型。

 二元运算符

在二元运算中,所有低级的数据类型都会转换为运算中级别最高的数据类型。也就是说,如果有一个操作数是double类型,其他操作数都会自动转换为double类型。如果运算中最高的数据类型是float,其他操作数都会转换为float类型。如果最高的数据类型为long,那么所有操作数都会自动转换为long类型。如果最高的数据类型为int,那么所有操作数都会自动转换成int类型。至于byte、short、char类型会自动转换为int或运算中最高的数据类型。

【例3.6】 在项目中创建类Conversion,在主方法中创建不同数值型的变量,实现将各变量的自动类型转换。(资源包\源码\03\3.06)

运行的结果如图3.10所示。

图3.10 实例执行结果

3.5.2 强制类型转换

当把高级别(即占用存储空间较大)的数据类型赋值给低级别(即占用存储空间较小)的数据类型时,必须进行的强制类型转换,其语法格式如下。

(数据类型)(表达式)

类型是要转换成的目标类型,例如int、short、double等。表达式是要转换的目标数据,它可以是任何基本类型的算术运算表达式。例如:

long类型的数值900没有超过short类型的取值范围,所以short类型的变量snum完全容纳了强制类型转换后的数值。

基本数据类型的强制类型转换需要注意数据完整性的问题,当把高级的数据类型强制转换为低级的数据类型时,如果数值超出低级数据类型的取值范围,数值将被截取,导致数据丢失、不完整。例如:

snum是short类型,数据长度是16位,而bnum是byte类型,长度为8位。当snum强制转换为byte类型时,数值“516”超出了byte类型的取值范围,这是只能从short类型截取低8位的数据赋值给byte类型的bnum变量,如图3.11所示。

图3.11 short转换为byte时必须截取数据

这样就造成了数据丢失,所以在使用强制数据类型转换时,一定要倍加小心。

注意

boolean布尔型的数值不能被牵制类型转换为其他数据类型,反之亦然。

【例3.7】 将long类型数值强制类型转换为其他数据类型,实例代码如下。(实例位置:资源包\源码\03\3.07)

实例运行结果如图3.12所示。

图3.12 实例运行结果

3.6 运算符

视频讲解

代表不同运算操作的符号称为运算符,执行运算的数据成为操作数。操作数与操作符按一定语法形式组成有意义的符号序列称为表达式,例如128+64、一个变量名都是表达式,其中变量名是最简单的表达式,它的值就是表达式的结果。表达式的结果也可以作为其他表达式的操作数,形成更加复杂的表达式。

3.6.1 赋值运算符

赋值运算符是以符号“=”表示,它主要用于修改变量的内容,其语法格式如下。

变量 = 表达式;

其功能是将“=”右侧的表达式的值赋值给左侧的变量。例如:

int num = 10-5+4;

该赋值运算将“=”右侧表达式“10-5+4”的结果“9”赋值给变量num。如果在“=”前面加上其他运算符,即构成了复合赋值运算符。例如“num += 1”,它等价于“num = num + 1”,复合赋值运算符集成了计算与赋值功能。

例如:使用赋值运算符为变量赋值,实例代码如下。

遵循赋值运算符的运算规则,可知变量c的赋值将先计算a+b的值,结果为15。然后将15赋值给变量c。因此“c=15”。

由于赋值运算符“=”处理时会先取得右方表达式处理后的结果,因此一个表达式中若含有两个以上的“=”运算符时,会从最右方“=”开始处理。

【例3.8】 在项目中创建类Eval,在主方法中定义变量,使用赋值运算符为变量赋值,实例代码如下。(实例位置:资源包\源码\03\3.08)

运行结果如图3.13所示。

图3.13 实例的运行结果

说明

在Java里可以把赋值运算符连在一起使用。如:

x = y = z = 5;

在这个语句中,变量x、y、z都得到同样的值5,但是在程序开发中不建议使用这种赋值语法。

3.6.2 算术运算符

Java中的算术运算符主要有+(加号)、−(减号)、*(乘号)、/(除号)、%(求余),它们都是二元运算符。Java中算术运算符的功能及使用方式如表3.6所示。

表3.6 Java算术运算符

其中“+”和“-”运算符还可以作为数据的正负符号,例如+5,-7。

注意

除法运算时,要记住0不可以做除数,如:int a = 5/0;系统会抛出异常信息“java.lang.Arithmetic Exception:/by zero”。

下面通过一个实例来介绍使用算术运算符的方法。

【例3.9】 项目中创建类Arith,在主方法中定义变量,使用算术运算符将变量的计算结果输出,实例代码如下。(实例位置:资源包\源码\03\3.09)

运行结果如图3.14所示。

图3.14 实例运行结果

3.6.3 自增和自减运算符

自增、自减运算符是一元算数运算符,可以作为前缀,也可以作为后缀使用。作用是使变量的值增1或减1。放在变量前面的自增、自减运算符,例如“++x”,会先将变量x的值加1,然后再引用该变量的值参与运算。放在操作符后面的自增、自减运算符,例如“x++”,是先引用变量的值参与表达式的运算,然后再将该变量加1。例如:

【例3.10】 输出自增与自减操作符作为前缀与后缀的表达式结果。请仔细分析实例运行结果,实例代码如下。(实例位置:资源包\源码\03\3.10)

运行结果如图3.15所示。

图3.15 实例运行结果

粗略的分析++num与num++的作用都相当于num=num+1。假设num=4,则

b=++num;先将num的值加1,然后赋给b,此时num值为5,b值为5。

b=num++;先将num的值赋给b,再将num的值变为5,此时num值为5,b值为4。

3.6.4 比较运算符

比较运算符也称关系运算符,属于二元运算符,其运算结果是boolean布尔类型。当运算符对应的两个操作数关系成立时,运算结果是true,否则是false。所有比较运算符通常用在条件语句中来作为判断的依据。比较运算符共有6个,如表3.7所示

表3.7 比较运算符

注意

相等“==”运算符和“=”赋值运算符要严格区分,不要混淆,如果在条件判断语句中,把“==”写成“=”会导致错误发生。

【例3.11】 在项目中创建类Compare,在主方法中创建整型变量,使用比较运算符对变量进行比较运算,将运算后的结果输出,实例代码如下。(实例位置:资源包\源码\03\3.11)

运行结果如图3.16所示。

3.16 实例运行结果

3.6.5 逻辑运算符

和比较运算符相比,逻辑运算符可以表示更加复杂的条件,例如连接几个关系表达式或者布尔值进行条件判断。而比较运算符只能进行一个简单的条件判断,例如x>y。

Java逻辑运算符包括“&&”逻辑与、“||”逻辑或、“!”逻辑非。逻辑运算符的操作数必须是boolean型表达式。在逻辑运算符中,除了“!”是一元运算符之外,其他都是二元运算符。表3.8按照逻辑运算符的优先级给出了它们的用法和含义。

表3.8 逻辑运算符

参与逻辑运算的对象必须是布尔类型的表达式或变量,经逻辑运算后的结果也是boolean布尔类型数据,逻辑运算的真值表如表3.9所示

表3.9 使用逻辑运算符进行逻辑运算

【例3.12】 输出与、或、非逻辑关系的运算结果,实例代码如下。(实例位置:资源包\源码\03\3.12)

运行结果如图3.17所示。

图3.17 实例运行结果

3.6.6 位运算符

位运算符用于处理整形和字符型的操作数。位运算是完全针对二进制位(bit)单位的操作。Java语言提供的位运算符如表3.10所示。

表3.10 逻辑运算符

说明

Java的位运算符中,“~”非运算是一元运算符,除此之外的都是二元运算符。

1.“按位与”运算

“按位与”运算的运算符为“&”,&是二元运算符。“按位与”运算的运算法则是:如果两个整型数据a、b对应位都是1,则该位结果才是1,否则为0。即

例如:153的二进制是10011001,46的二进制是00101110,这两个数按位与运算的方法如下,括号中的是十进制数。

2.“按位或”运算

“按位或”运算的运算符为“|”,它是二元运算符。“按位或”运算的运算法则是:如果两个操作数对应位都是0,则该位的结果才是0,否则为1。即

例如:153的二进制是10011001,46的二进制是00101110,这两个数按位进行或运算的方法如下,括号中的是十进制数。

3.“按位取反”运算

“按位取反”运算也称“按位非”运算,运算符为“~”,~为一元运算符。它的运算法则是操作数二进制中的1修改为0,0修改为1。即

例如:153的二进制是10011001,把它按位取反的结果为01100110

4.“按位异或”运算

“按位异或”运算的运算符位“^”,^为二元运算符。“按位异或”运算的运算法则是:当两个操作数的二进制对应位相同(同时为0或同时为1)时,结果为0,否则为1。即

例如:153的二进制是10011001,46的二进制是00101110,这两个数按位进行异或运算的方法如下,括号中的是十进制数。

5.位移运算

除了上述按位运算符之外,还可以对数据按二进制位进行移位操作,Java中的移位运算符有3种。

 << 左移

 >> 右移

 >>> 无符号右移

左移就是将左边的操作数在内存中的二进制数据左移右边操作数指定的位数,左边移空的部分补0。右移则复杂一些。当使用“>>”符号时,如果最高位是0,左移空的位就填入0;如果最高位是1,右移空的位就添入1,如图3.18所示。

图3.18 右移

Java还提供了无符号右移“>>>”,不管最高位是0还是1,左移空的高位都添入0。

注意

移位运算符适用的数据类型有byte、short、char、int、long。

技巧

移位能让我们实现整数除以或乘以2的n次方的效果,如:y<<2于y*4的结果相同;y>>1的结果与y/2的结果相同。总之,一个数左移n位,就是将这个数乘以2的n次方,一个数右移n位,就是将这个数除以2的n次方。

3.6.7 三元运算符

三元运算符的使用格式如下。

条件式?值1:值2

三元运算符的运算规则为:若条件式的值为true,则整个表达式取值1,否则取值2。例如:

int x = 1;
int y = 2;
int num = x < y ? 10 : 20;

如上例所示,当表达式“x < y”的运算结果返回true时,则变量num取值10,当表达式“x < y”返回false时,则变量num取值20。上例的结果为num等于10。

【例3.13】 使用三元运算符求两数中的最小数,实例代码如下。(实例位置:资源包\源码\03\3.13)

运行结果如图3.19所示。

图3.19 实例运行结果

3.6.8 运算符优先级

Java中运算符的优先级决定了表达式中运算执行的先后顺序。如果两个运算有相同的优先级,那么在左边的表达式要比在右边的表达式先被处理。表3.11介绍了在Java里众多运算符的特定的优先级。

表3.11 运算符的优先级别

技巧

在编写程序时尽量使用括号“()”运算符号来限定运算次序,以免产生错误的运算顺序。

3.7 编码规范

编码规范对于程序开发人员很重要,遵循编码规范所编写的程序代码可读性高,有维护价值,如果你编写的程序代码别人看不懂、甚至没有人愿意看,那么你所编写的程序代码就一文不值,而且再过一段时间,该程序的编写人员也会忘记程序的业务逻辑,无法有效地维护程序代码。

读者在学习开发的过程中一定要养成良好的编码规范,对于规整的代码格式会给程序的开发与日后的维护提供很大方便。本节对编码规则做了简单总结,供读者学习。

 每条语句要单独占一行,一条命令要以分号结束。

注意

在程序代码中的分号必须为英文状态下,初学者经常会将“;”写成中文状态下的“;”,这个时候编译器会报出illegal character(非法字符)这样的错误信息。

 在声明变量时,尽量使每个变量的声明单独占一行,即使是相同的数据类型也要将其放置在单独的一行上。这样有助于添加注释。对于局部变量应在声明的同时对其进行初始化。

 在Java代码中,关键字与关键字间如果有多个空格,这些空格均被视作一个。例如:

而多余的空格没有任何意义,为了便于理解、阅读,应控制好空格的数量。

 变量的命名要尽量使用有意义的名称,变量的第一个单词小写,第二个以后的单词要求首字母大写。例如:productPrice、age、name、userName。

 类名和接口的命名不但要求使用有意义的单词而且所有单词的首字母都要大写,例如:ProductFactory、UserInfo。

 常量的所有字母全部大写,多个单词使用下画线(_)分割。例如:PRODUCT_UNIT。

 适当的缩进代码,使代码对齐。如果使用Eclipse开发工具,按下Ctrl+Shift+F快捷键将自动格式化程序代码。

 为了方便日后的维护,不要使用技术性很高、难懂易混淆判断的语句。由于程序的开发与维护不能是同一个人,所以应尽量使用简单的技术完成程序需要的功能。

 对于关键的方法要多加注释,这样有助于阅读者很快地了解代码结构。

3.8 实战

视频讲解

3.8.1 输出字节bit位的值

一个字节有8位(bit)组成,位是最小单位,字节的位从低到高依次排序,索引下标是0~7,如图3.20所示。(实例位置:资源包\源码\03\实战\01)

图3.20 位的排列

下面的实例通过位移运算计算二进制每个数位的值,并输出到控制台,实例运行效果如图3.21所示。

3.8.2 判断奇偶数

三元运算符是if…else…条件语句的简写格式,它可以完成简单的条件判断,下面利用这个三元运算符实现奇偶数的判断。程序运行结果如图3.22所示。程序接收用户输入的整数数字,然后判断是奇数还是偶数,并将判断结果输出到控制台。(实例位置:资源包\源码\03\实战\02)

图3.21 实例运行结果

图3.22 实例运行结果

3.8.3 简单数据加密

通过位运算的“^”异或运算符把字符串与一个指定的值进行异或运算,从而改变字符串每个字符的值,这样就可以得到一个加密后的字符串,如图3.23所示。当把加密后的字符串作为程序输入内容,异或运算会把加密后的字符串还原为原有字符串的值,如图3.24所示。下面请读者完成这个情景应用。(实例位置:资源包\源码\03\实战\03)

图3.23 加密效果

图3.24 解密效果

3.8.4 判断闰年

为了弥补因人为历法规定造成的年度天数与地球实际公转周期的时间差,设立了366天的闰年,闰年的二月份有29天。下面使用程序完成闰年的判断,判断的年份由用户输入,程序运行结果如图3.25所示。(实例位置:资源包\源码\03\实战\04)

图3.25 实例运行结果

3.8.5 异或运算实现变量值交换

变量的互换常见于数组排序算法中,当判断两个数组元素需要交互时,将创建一个临时变量来共同完成互换,临时变量的创建增加了系统资源的消耗,如果需要交换的是两个整数类型的变量,那么可以使用更高效的方法,下面演示如何使用异或位运算实现两个整数类型变量的高效互换,程序运行结果如图3.26所示。(实例位置:资源包\源码\03\实战\05)

图3.26 实例运行结果