3.3 运算符
运算符是程序设计语言中重要的构成元素之一,运算符可以细分为算术运算符、位运算符、关系运算符、逻辑运算符和其他运算符。在本节的内容中,我们将详细讲解Java语言中运算符的基本知识。
知识点讲解:
3.3.1 算术运算符
在数学中有加减乘除运算,算术运算符(Arithmetic Operator)就是用来处理数学运算的符号,这是最简单、也最常用的符号。在数字处理中几乎都会用到算术运算符,算术运算符可以分为基本运算符、取余运算符和递增或递减运算符等。具体说明如表3-2所示。
表3-2 算术运算符
1.基本运算符
在Java程序中,使用最广泛的便是基本运算符。
实例3-8
使用基本运算符的加减乘除4种运算
源码路径:daima\3\JiBen1.java
实例文件JiBen1.java的主要实现代码如下所示。
public static void main(String args[]) { ① int a=12; ② int b=4; //下面开始使用4种运算符 ③ System.out.println(a-b); ④ System.out.println(a+b); ⑤ System.out.println(a*b); ⑥ System.out.println(a/b); }
拓展范例及视频二维码
范例3-8-01:演示基本运算的过程
源码路径:演练范例\3-8-01\
范例3-8-02:实现加密处理
源码路径:演练范例\3-8-02\
行①②分别定义两个int类型的变量a和b,设置a的初始值是12,设置b的初始值是4。
行③使用println()函数输出变量a和变量b的差。
行④使用println()函数输出变量a和变量b的和。
行⑤使用println()函数输出变量a和变量b的乘积。
行⑥使用println()函数输出变量a除以b的结果。
执行后的结果如图3-8所示。
图3-8 使用基本运算符
注意:分母为零的情况要引起重视。计算机中的运算和数学运算有些不同,一般来说分母不能为零,为零会发生程序错误,但有时程序中分母为零并不是错误,例如下面的代码(daima\3\Jiben.java)。
public class Jiben { public static void main(String args[]){ int AAA=126; //定义int类型变量AAA的值是126 //整型数据的分母不能为零 System.out.println(a/0); } }
编译上述代码后会得到图3-9所示的结果。
图3-9 运行结果
上面的结果提示用户分母不能为零,如果将上述代码中的“int AAA=126”改为“double AAA=126”,编译后会得到图3-10所示的结果。
图3-10 更改后的运行结果
对于基本运算符,只要将分子定义为double型,分母为零就是正确的,得到的值是无穷大,这一点希望初学者能够加以理解。
2.取余运算符
在现实应用中,除法运算的结果不一定总是整数,计算结果是使用第一个运算数除以第二个运算数,得到整数结果后剩下的值,就是余数。在Java程序中,取余运算符用于计算除法操作中的余数。由于取余运算符也需要进行除法运算,因此如果取余运算的两个运算数都是整数类型,则求余运算的第二个运算数不能是0,否则将引发除以零异常。如果取余运算的两个操作数中有1个或2个是浮点数,则允许第二个操作数是0或0.0,只是求余运算的结果是NaN(NaN是Java中的特殊数字,表示非数字类型)。0或0.0对零以外的任何数求余都将得到0或0.0。
注意:取余运算符是一种很奇怪的运算符,在数学运算中很少被提及,其实可以很简单地理解它。取余运算符一般被用在除法中,它的取值不是商,而是余数。例如5/2,取余运算符取的是余数,所以结果是1,而不是商值结果2.5。
实例3-9
使用“%”运算符
源码路径:daima\3\Yushu.java
实例文件Yushu.java的主要实现代码如下所示:
public static void main(String[] args) { //求余数 ① int A=19%3; ② int K=-19%-3; ③ int Q=19%-3; ④ int J=-19%3; ⑤ System.out.println("A=19%3的余数"+A); ⑥ System.out.println("K=-19%-3的余数"+K); ⑦ System.out.println("Q=19%-3的余数"+Q); ⑧ System.out.println("J=-19%3的余数"+J); }
拓展范例及视频二维码
范例3-9-01:演示取余运算的规律
源码路径:演练范例\3-9-01\
范例3-9-02:用三元运算符判断奇偶数
源码路径:演练范例\3-9-02\
行①定义1个int类型的变量A,设置其初始值是19除以3的余数。
行②定义1个int类型的变量K,设置其初始值是-19除以-3的余数。
行③定义1个int类型的变量Q,设置其初始值是19除以-3的余数。
行④定义1个int类型的变量J,设置其初始值是-19除以3的余数。
行⑤⑥⑦⑧分别使用println()函数输出4个变量A、K、Q和J的值。
执行后的结果如图3-11所示。
图3-11 取余运算
3.递增和递减运算符
递增和递减运算符分别是指“++”和“--”,每执行一次,变量将会增加1或减少1,它们可以放在变量的前面,也可以放在变量的后面。无论哪一种形式都能改变变量的结果,但它们有一些不同,这种变化让初学编程的人感到疑惑。递增、递减对于刚学编程的人来说是难点,读者一定要加强理解。理解的不是++与--的问题,而是在变量前用还是在变量后用的问题。
实例3-10
使用递增和递减运算符
源码路径:daima\3\Dione.java
实例文件Dione.java的主要实现代码如下所示。
public static void main(String args[]){ ① int a=199; ② int b=1009; //数据的递增与递减 ③ System.out.println(a++); ④ System.out.println(a); ⑤ System.out.println(++a); ⑥ System.out.println(b--); ⑦ System.out.println(b); ⑧ System.out.println(--b); }
拓展范例及视频二维码
范例3-10-01:演示递增和递减运算符的用法
源码路径:演练范例\3-10-01\
范例3-10-02:更精确地运用浮点数
源码路径:演练范例\3-10-02\
行①②分别定义两个int类型的变量a和b,设置a的初始值是199,设置b的初始值是1009。
行③使用println()函数输出a++的值,此处先输出,然后才加1,所以结果是199。
行④使用println()函数输出a的值,因为在行②的最后加1了,所以这里的结果是200。
行⑤使用println()函数输出++a的值,此处先加1,再输出。这里要紧接着行④中a的值200,所以本行的结果是201。
行⑥使用println()函数输出b--的值,此处先输出b的值,再将b减1,所以本行的结果是1009。
行⑦使用println()函数输出b的值,因为在行⑥的最后减1了,所以这里的结果是1008。
行⑧使用println()函数输出--b的值,此处先减1,然后执行程序。这里要紧接着行⑦中b的值1008,所以本行的结果是1007。
执行后的结果如图3-12所示。
图3-12 使用递增和递减运算符
3.3.2 关系运算符和逻辑运算符
在Java程序设计中,关系运算符(Relational Operator)和逻辑运算符(Logical Operator)显得十分重要。关系运算符定义值与值之间的相互关系,逻辑(logical)运算符定义可以用真值和假值链接在一起的方法。
1.关系运算符
在数学运算中有大于、小于、等于、不等于关系,在程序中可以使用关系运算符来表示上述关系。表3-3中列出了Java中的关系运算符,通过这些关系运算符会产生一个结果,这个结果是一个布尔值,即true或false。在Java中,任何类型的数据,都可以用“= =”比较是不是相等,用“!=”比较是否不相等,只有数字才能比较大小,关系运算的结果可以直接赋予布尔变量。
表3-3 关系运算符
2.逻辑运算符
布尔逻辑运算符是最常见的逻辑运算符,用于对布尔型操作数进行布尔逻辑运算,Java中的布尔逻辑运算符如图3-4所示。
表3-4 逻辑运算符
逻辑运算符与关系运算符运算后得到的结果一样,都是布尔类型的值。在Java程序设计中,“&&”和“”布尔逻辑运算符不总是对运算符右边的表达式求值,如果使用逻辑与“&”和逻辑或“|”,则表达式的结果可以由运算符左边的操作数单独决定。通过表3-5,读者可以了解常用逻辑运算符“&&”、“”、“! ”运算后的结果。
表3-5 逻辑运算符
在接下来的内容中,将通过一个具体实例来说明关系运算符的基本用法。
实例3-11
使用关系运算符
源码路径:daima\3\guanxi.java
实例文件guanxi.java的主要实现代码如下所示。
public static void main(String args[]){ ① char a='k'; //为a赋值 ② char b='k'; //为b赋值 ③ char c='A'; //为c赋值 ④ int d=100; //为d赋值 ⑤ int e=101; //为e赋值 ⑥ System.out.println(a==b); //下面开始分别输出对应的运算结果 ⑦ System.out.println(b==c); ⑧ System.out.println(b! =c); ⑨ System.out.println(d<e); }
拓展范例及视频二维码
范例3-11-01:演示逻辑运算符的用法
源码路径:演练范例\3-11-01\
范例3-11-02:不用乘法运算符实现2×16
源码路径:演练范例\3-11-02\
行①②③分别定义3个cha类型的变量a、b和c,并分别设置它们的初始值。
行④⑤分别定义两个int类型的变量d和e,并分别设置它们的初始值。
行⑥使用println()函数输出a==b的结果。
行⑦使用println()函数输出b==c的结果。
行⑧使用println()函数输出b!=c的结果。
行⑨使用println()函数输出d<e的结果。
执行后的结果如图3-13所示。
图3-13 使用关系运算符
3.3.3 位逻辑运算符
在Java程序设计中,使用位逻辑运算符来操作二进制数据。读者必须注意,位逻辑运算符只能操作二进制数据。如果用在其他进制的数据中,需要先将其他进制的数据转换成二进制数据。位逻辑运算符(Bitwise Operator)可以直接操作整数类型的位,这些整数类型包括long、int、short、char和byte。Java语言中位逻辑运算符的具体说明如表3-6所示。
表3-6 位逻辑运算符
因为位逻辑运算符能够在整数范围内对位操作,所以这样的操作对一个值产生什么效果是很重要的。具体来说,了解Java如何存储整数值并且如何表示负数是非常有用的。表3-7中演示了操作数A和操作数B按位逻辑运算的结果。
表3-7 位逻辑运算结果
移位运算符把数字的位向右或向左移动,产生一个新的数字。Java的右移运算符有两个,分别是>>和>>>。
❑ >>运算符:把第一个操作数的二进制码右移指定位数后,将左边空出来的位以原来的符号位填充。即,如果第一个操作数原来是正数,则左边补0;如果第一个操作数是负数,则左边补1。
❑ >>>:把第一个操作数的二进制码右移指定位数后,将左边空出来的位以0填充。
在接下来的内容中,将通过一个具体实例来说明位逻辑运算符的基本用法。
实例3-12
使用位逻辑运算符
源码路径:daima\3\wei.java
实例文件wei.java的主要实现代码如下所示。
public class wei { public static void main(String[] args){ ① int a=129; ② int b=128; ③ System.out.println("a和b 与的结果是:"+(a&b)); } }
拓展范例及视频二维码
范例3-12-01:演示与运算符的用法
源码路径:演练范例\3-12-01\
范例3-12-02:演示非运算符的用法
源码路径:演练范例\3-12-02\
行①②分别定义两个cha类型的变量a和b,并分别设置它们的初始值。
行③使用println()函数输出a&b的结果。a的值是129,转换成二进制就是10000001;而b的值是128,转换成二进制就是10000000。根据与运算符的运算规律,只有两个位都是1,运算结果才是1,所以a&b的运算过程如下。
a 10000001 b 10000000 a&b 10000000
由此可以知道10000000的结果就是10000000,转换成十进制就是128。执行后的结果如图3-14所示。
图3-14 执行结果
3.3.4 条件运算符
条件运算符是一种特殊的运算符,也被称为三目运算符。它与前面所讲的运算符有很大不同,Java中提供了一个三目运算符,其实这跟后面讲解的if语句有相似之处。条件运算符的目的是决定把哪个值赋给前面的变量。在Java语言中使用条件运算符的语法格式如下所示。
变量=(布尔表达式)? 为true时赋予的值:为false时赋予的值;
实例3-13
使用条件运算符
源码路径:daima\3\tiao.java
实例文件tiao.java的主要实现代码如下所示。
public static void main(String args[]){ ① double chengji=70; ② String Tiao=(chengji>=90)? "已经很优秀": "不是很优秀, 还需要努力!"; //输出结果 ③ System.out.println(Tiao); }
拓展范例及视频二维码
范例3-13-01:根据条件的不同实现赋值
源码路径:演练范例\3-13-01\
范例3-13-02:实现两个变量的互换
源码路径:演练范例\3-13-02\
行①定义double类型的变量chengji,设置其初始值是70。
行②定义String类型的变量Tiao,并赋值显示条件运算结果。如果设置变量chengji大于或等于90,则输出“已经很优秀”的提示;反之,就输出“不是很优秀,还需要努力!”的提示。
行③使用println()函数输出Tiao的值。因为在代码中设置了“chengji=70”,所以执行后的结果如图3-15所示。
图3-15 执行结果
3.3.5 赋值运算符
赋值运算符是等号“=”,Java中的赋值运算与其他计算机语言中的赋值运算一样,起到赋值的作用。在Java中使用赋值运算符的格式如下所示。
var = expression;
其中,变量var的类型必须与表达式expression的类型一致。
赋值运算符有一个有趣的属性,它允许我们对一连串变量进行赋值。请看下面的代码。
int x, y, z; x = y = z = 100;
在上述代码中,使用一条赋值语句将变量x、y、z都赋值为100。这是由于“=”运算符表示右边表达式的值,因此z = 100的值是100,然后该值被赋给y,并依次被赋给x。使用“字符串赋值”是给一组变量赋予同一个值的简单办法。在赋值时类型必须匹配,否则将会出现编译错误。
实例3-14
演示赋值类型不匹配的错误
源码路径:daima\3\fuzhi.java
实例文件fuzhi.java的主要实现代码如下所示。
public static void main(String args[]){ //定义的字节数据 ① byte a=9; ② byte b=7; ③ byte c=a+b; ④ System.out.println(c); }
拓展范例及视频二维码
范例3-14-01:扩展赋值运算符的功能
源码路径:演练范例\3-14-01\
范例3-14-02:演示运算符的应用
源码路径:演练范例\3-14-02\
行①分别定义byte类型的变量a和b,设置a的初始值是9,设置b的初始值是7。
行②定义byte类型的变量c,并赋值为a和b的和。Java语言规定:byte类型的变量在进行加减乘除和余数运算时会自动变为int类型。所以,本行的变量a和b会在计算时自动转换成int类型,但是本行在左侧已经明确声明为了byte类型,所以会出错。
行③使用println()函数输出变量c的值。执行后会提示类型不匹配错误,执行结果如图3-16所示。
图3-16 类型不匹配错误
注意:在Java中可以对赋值运算符进行扩展,其中最为常用的有如下扩展操作。
❑ +=:对于x+=y,等效于x=x+y。
❑ -=:对于x-=y,等效于x=x-y。
❑ *=:对于x*=y,等效于x=x*y。
❑ /=:对于x/=y,等效于x=x/y。
❑ %=:对于x%=y,等效于x=x%y。
❑ &=:对于x&=y,等效于x=x&y。
❑ |=:对于x|=y,等效于x=x|y。
❑ ^=:对于x^=y,等效于x=x^y。
❑ <<=:对于x<<=y,等效于x=x<<y。
❑ >>=:对于x>>=y,等效于x=x>>y。
❑ >>>=:对于x>>>=y,等效于x=x>>>y。
另外,在后面的学习中我们会接触到equals()方法,此方法和赋值运算符= =的功能类似。要想理解两者之间的区别,我们需要从变量说起。Java中的变量分为两类,一类是值类型,它存储的是变量真正的值,比如基础数据类型,值类型的变量存储在内存的栈中;另一类是引用类型,它存储的是对象的地址,与该地址对应的内存空间中存储的才是我们需要的内容,比如字符串和对象等,引用类型的变量存储在内存中的堆中。赋值运算符= =比较的是值类型的变量,如果比较两个引用类型的变量,比较的就是它们的引用地址。equals()方法只能用来比较引用类型的变量,也就是比较引用的内容。
= =运算符比较的是左右两边的变量是否来自同一个内存地址。如果比较的是值类型(基础数据类型,如int和char之类)的变量,由于值类型的变量存储在栈里面,当两个变量有同一个值时,其实它们只用到同一个内存空间,所以比较的结果是true。
eqluals()方法是Object类的基本方法之一,所以每个类都有自己的equals()方法,功能是比较两个对象是否是同一个,通俗的理解就是比较这两个对象的内容是否一样。
3.3.6 运算符的优先级
数学中的运算都是从左向右运算的,在Java中除了单目运算符、赋值运算符和三目运算符外,大部分运算符也是从左向右结合的。单目运算符、赋值运算符和三目运算符是从右向左结合的,也就是说,它们是从右向左运算的。乘法和加法是两个可结合的运算,也就是说,这两个运算符左右两边的操作符可以互换位置而不会影响结果。
运算符有不同的优先级,所谓优先级,就是在表达式运算中的运算顺序。表3-8中列出了包括分隔符在内的所有运算符的优先级,上一行中的运算符总是优先于下一行的。
表3-8 Java运算符的优先级
根据表3-9所示的运算符的优先级,假设int a=3,开始分析下面变量b的计算过程。
int b= a+2*a
程序先执行2*a得到6,再计算a+6得到9。使用圆括号( )可以改变程序的执行过程,例如:
int b=(a+2)*a
先执行a+2得到5,再用5*a得到15。
实例3-15
使用表达式与运算符
源码路径:daima\3\biaoone.java
实例文件biaoone.java的主要实现代码如下所示。
public static void main(String args[]){ ① int a=231; ② int b=4; ③ int h=56; ④ int k=45; ⑤ int x=a+h/b; ⑥ int y=h+k; ⑦ System.out.println(x); ⑧ System.out.println(y); ⑨ System.out.println(x==y); }
拓展范例及视频二维码
范例3-15-01:演示运算符的优先级
源码路径:演练范例\3-15-01\
范例3-15-02:演示关系运算符的应用
源码路径:演练范例\3-15-02\
行①②③④分别定义4个int类型的变量a、b、h和k,设置a的初始值是231,设置b的初始值是4,设置h的初始值是56,设置k的初始值是45。
行⑤定义一个int类型的变量x,并赋值为a+h/b,根据优先级规则,先计算除法h/b,后计算加法。
行⑥定义一个int类型的变量y,并赋值为h+k。
行⑦⑧⑨使用println()函数分别输出变量x、y和表达式x= =y的值。
执行后的结果如图3-17所示。
图3-17 执行结果
注意:书写Java运算符有两点注意事项。
(1)不要把一个表达式写得过于复杂,如果一个表达式过于复杂,就把它分成几步来完成。
(2)不要过多地依赖运算符的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用圆括号( )来控制表达式的执行顺序。