《Java和Android开发学习指南(第2版)》——第2章,第2.8节操作符

简介:

本节书摘来自异步社区《Java和Android开发学习指南(第2版)》一书中的第2章,第2.8节操作符,作者 【加】Budi Kurniawan,更多章节内容可以访问云栖社区“异步社区”公众号查看

2.8 操作符
计算机程序是实现某一功能的操作汇集在一起的一个集合。有很多种类型的操作,包括加法、减法、乘法、除法和位移。在本小节中,我们将学习各种Java操作。

一个操作符会对一个、两个或三个操作数执行操作。操作数是操作的目标,而操作符则是表示动作的一个符号。例如,如下是加法操作:

x + 4

在这个例子中,x和4是操作数,+是操作符。

一个操作符可能返回一个结果,也可能不返回结果。

操作符和操作数的任何合法的组合,叫作表达式(expression)。例如,x+4是一个表达式。一个布尔表达式会得到真或假;一个整数表达式会得到一个整数;浮点数表达式的结果是一个浮点数。
只需要一个操作数的操作符叫作一元操作符(unary operator),Java中有几个一元操作符。二元操作符(binary operator)接受两个操作数,这是Java操作符中最常见的类型。还有一个三元操作符(ternary operator)? :,它需要3个操作数。


81bacf9ec1faa326ef9829bfb0b68abf82b4d31e

在Java中,操作符分为6类:

一元操作符。
算术操作符。
关系和条件操作符。
位移和逻辑操作符。
赋值操作符。
其他操作符。
下面分别介绍每一种操作符。

2.8.1 一元操作符
一元操作符在一个操作数上起作用。有6个一元操作符,本节中将一一介绍。

一元减操作符
一元减操作符返回其操作数的负值。操作数必须是一个数字值,或者是一个数值基本类型的变量。例如,在下面的代码中,y的值是-4.5;

float x = 4.5f; 
float y = -x;

一元加操作符
一元加操作符返回其操作数的值。操作数必须是一个数值类型,或者是一个数值类型的变量。例如,在如下的代码中,y的值是4.5。

float x = 4.5f; 
float y = +x;

这个操作符没有那么重要,因为不使用它也不会有什么差别。

自增操作符++
自增操作符将其操作数增加1。操作数必须是一个数值基本类型的变量。操作符可以出现在操作数之前或之后。如果操作符出现在操作符之前,它叫作前缀自增操作符。如果它写在操作数之后,叫作后缀自增操作符。

作为例子,下面展示了一个前缀自增操作符:

int x = 4; 
++x;
在++x之后,x的值变为5。前面的代码等同于:

int x = 4; 
x++;
在x++之后,x的值为5。

然而,如果在同一个表达式中,自增操作符的结果需要赋值给另一个变量,那么,前缀操作符和后缀操作符之间就存在差异了。考虑如下的例子:

int x = 4; 
int y = ++x; 
// y = 5, x = 5

在赋值之前,使用了前缀自增操作符。x自增到5,并且随后将其值复制给y。

查看一下如下的后缀自增操作符的用法。

int x = 4; 
int y = x++; 
// y = 4, x = 5

使用后缀自增操作符,在将操作数(x)的值赋值给另一个变量(y)之后,才将操作数的值加1。

注意,自增操作符对于int类型来说是最常用的。它对于其他的数字基本类型(例如float和long)来说,也是适用的。

自减操作符--
自减操作符将操作数的值减去1。操作数必须是数值基本类型的一个变量。和自增操作符类似,它也有前缀自减操作符和后缀自减操作符。例如,如下的代码将x的值自减,并将其赋值给y。
``
int x = 4;
int y = --x;
// x = 3; y = 3

在如下的示例中,使用了后缀自减操作符:

int x = 4;
int y = x--;
// x = 3; y = 4

逻辑取反操作符!
逻辑取反操作符只适用于一个布尔基本类型或者java.lang.Boolean的一个实例。如果操作数是false,这个操作符的值为true;如果操作数为true,这个操作符的值为false。例如:

boolean x = false;
boolean y = !x;
// at this point, y is true and x is false

位取反操作符~
位取反操作符的操作数必须是一个整数基本类型或者整数基本类型的一个变量。其结果是对操作数的按位取反。例如:

int j = 2;
int k = ~j; // k = -3; j = 2

要理解这个操作符是如何工作的,需要将操作数转换为一个二进制数,并且将所有的位都取反。整数2的二进制形式是:

0000 0000 0000 0000 0000 0000 0000 0010
对其按位取反之后,得到

1111 1111 1111 1111 1111 1111 1111 1101

而这是整数-3的二进制表示。

**2.8.2 算术操作符**
有5种类型的算术操作符,分别是加法、减法、乘法和除法,以及模除。下面将分别介绍这5种操作符。

加法操作符+
加法操作符将两个操作数相加。操作数的类型必须可以转换为一个数值基本类型。例如:

byte x = 3;
int y = x + 5; // y = 8
要确保接受加法结果的变量有足够的容量。例如,在如下的代码中,k的值是-294967296而不是40亿。

int j = 2000000000; // 2 billion
int k = j + j; // not enough capacity. A bug!!!
如下的代码则像预期的那样工作:

long j = 2000000000; // 2 billion
long k = j + j; // the value of k is 4 billion

减法操作符-
减法操作符在两个操作数之间执行减法。操作数的类型必须可以转换为一个数值类型。例如:

int x = 2;
int y = x – 1; // y = 1

乘法操作符*
乘法操作符在两个操作数之间执行乘法。操作数的类型必须能够转换为一种数值基本类型。例如:

int x = 4;
int y = x * 4; // y = 16

除法操作符/
除法操作符在两个操作数之间执行除法。左操作数除以右操作数。除数和被除数都必须是能够转换一种数值基本类型的类型。例如:

int x = 4;
int y = x / 2; // y = 2

注意,在运行时,如果除数为0的话,将会导致一个错误。使用/操作符的除法的结果,总是一个整数。如果除数不能够将被除数除尽,余数将会被忽略。例如:

int x = 4;
int y = x / 3; // y = 1

第5章将会介绍java.lang.Math类,它能够执行更为复杂的除法操作。

模除操作符%
模除操作符执行两个操作数之间的除法,但是返回余数。左操作数是被除数,右操作数是除数。被除数和除数都必须是能够转换为数值基本类型的一种类型。例如,如下操作的结果是2。

8 % 3
2.8.3 相等操作符
有两种相等操作符,==(相等)和!=(不相等),它们都可以作用于两个整数、浮点数、字符或布尔类型的操作数。相等操作符的结果也是一个布尔类型。

例如,如下的比较,结果为真。

int a = 5; 
int b = 5; 
boolean c = a == b;
又如

boolean x = true;
boolean y = true;
boolean z = x != y;

比较之后,z的值为false,因为x等于y。

**2.8.4 关系操作符**
一共有5种关系操作符:<、>、<=、>=以及instanceof。前4个操作符都将在本节中介绍。第7章将会介绍instanceof。

<、>、<=和>=操作符作用于两个操作数之上,它们的类型必须能够转换为一种数值基本类型。关系操作符返回一个布尔值。<操作符计算左边操作数的值是否小于右边的操作数的值。例如,如下的操作返回假:

9 < 6

>操作符计算左操作数的值是否大于右操作数的值。例如,如下的操作返回真:

9 > 6

<=操作符测试左操作数的值是否大于或等于右操作数的值。例如,如下的操作结果为假:

9 <= 6

>=操作符测试左操作数的值是否大于或等于右操作数的值。例如,如下操作返回真:

9 >= 9

**2.8.5 条件操作符**
一共有3个条件操作符:AND操作符&&、OR操作符||以及?:操作符。下面详细地介绍每一种操作符。

&&操作符
&&操作符接受两个表达式作为操作数,并且这两个表达式都必须返回一个值,而这个值必须能够转换为一个布尔类型。如果两个操作数的结果都为真,那么它返回真。否则,它返回假。如果左操作数为假,右操作数就不必计算了。例如,如下的例子返回假:

(5 < 3) && (6 < 9)

||操作符
||操作符接受两个表达式作为操作数,并且这两个表达式都必须返回一个值,而这个值必须能够转换为一个布尔类型。如果两个操作数有一个结果为真,那么||返回真。如果左操作数为真,右操作数就不必计算了。例如,如下的例子返回真:

(5 < 3) || (6 < 9)
? :操作符
? :操作符有3个操作数。其语法如下:

expression1 ? expression2 : expression3 
这里,expression1必须返回一个能够转换为布尔类型的值。如果expression1的结果为真,返回expression2,否则的话,返回expression3。

例如,如下的表达式返回4。

(8 < 4) ? 2 : 4

**2.8.6 位移操作符**
位移操作符接受两个操作数,操作符类型必须能够转换为一个整数基本类型。左操作数是要位移的值,右操作数表示位移的距离。如下是3种类型的位移操作符:

向左位移操作符<<。
向右位移操作符>>。
无符号位向右位移操作符>>>。
向左位移操作符<<
向左位移操作符会把一个数字向左位移,右边的位用0来补充。n << s的值是将n向左移动s位。相当于将操作数乘以2的s次幂。

例如,将一个值为1的int向左位移3个位置(1<<3),结果是8。为了搞清楚这一点,需要将操作数转换为一个二进制数。

0000 0000 0000 0000 0000 0000 0000 0001

向左位移3位后,得到:

0000 0000 0000 0000 0000 0000 0000 1000

其结果等于8(等同于1*23)。

另一条规则是,如果左操作数是一个int类型,只有位移距离的前5位会使用。换句话说,位移距离必须在0~31之间。如果传递的数字大于31,只有前5位会使用。也就是说,如果x是一个int类型,x<<32等同于x<<0;x<<33等同于x<<1。

如果左操作数是long类型,位移距离中只有前6位会使用。换句话说,实际使用的位移距离的范围在0~63之间。

向右位移操作符>>
向右位移操作符>>将左边的操作数向右位移右边操作数所指定的位数。n>>s是将n向右移动s位。结果是n/2s。

例如,16 >> 1等于8。为了证实这一点,写出16的二进制表示如下。

0000 0000 0000 0000 0000 0000 0001 0000

然后,将其向右移动1位,得到:

0000 0000 0000 0000 0000 0000 0000 1000

结果等于8。

无符号向右位移操作符>>>
n>>>s的值取决于n是正数还是负数。对于一个正数n,其结果值和n>>s相同。

如果n是负值,其结果取决于n的类型。

如果n是一个int类型,结果的值是(n>>s)+(2<<~s)。如果n是一个long类型,结果的值是(n>>s)+(2L<<~s)。

2.8.7 赋值操作符
一共有12个赋值操作符,如下所示:

= += -= *= /= %= <<= >>= >>>= &= ^= |=
左操作数必须是一个变量。例如:

int x = 5;
除了赋值操作符=以外,其他的操作符都以相同的方式工作,而且,你应该看到,其中的每一个都由两个操作符组成。例如,+=实际上是+和=。赋值操作符<<=也有两个操作符,分别是<<和=。

由两部分组成的赋值操作符是这样工作的,对两个操作数都应用第一个操作符,然后,将结果赋值给左操作数。例如,x+=5等同于x = x + 5。

x -= 5等同于x = x - 5

x <<= 5等同于x = x << 5

x &= 5得到的结果和x = x & 5相同

**2.8.8 整数按位操作符& | ^**
位操作符& | ^在两个操作数上执行位操作,操作数的类型必须能够转换为整数。&表示一个AND操作,|表示一个OR操作,^表示一个异或操作。例如:

0xFFFF & 0x0000 = 0x0000
0xF0F0 & 0xFFFF = 0xF0F0
0xFFFF | 0x000F = 0xFFFF
0xFFF0 ^ 0x00FF = 0xFF0F

**2.8.9 逻辑操作符 & | ^**
逻辑操作符& | ^在两个操作数上执行逻辑操作,这两个操作数能够转换为布尔类型。&表示一个AND操作。|表示一个OR操作,^表示一个异或操作。例如:

true & true = true
true & false = false
true | false = true
false | false = false
true ^ true = false
false ^ false = false
false ^ true = true

2.8.10 操作符优先级
在大多数程序中,一个表达式中常常会出现多个操作符,例如:

int a = 1; 
int b = 2; 
int c = 3; 
int d = a + b * c;
在代码执行之后,结果是多少?如果你说是9,那么你错了。实际结果是7。

乘法操作符*的优先级比加法操作符+的优先级高。因此,乘法将会在加法之前执行。如果你想要先执行加法,可以使用圆括号:

int d = (a + b) * c;

后者将会把9赋值给d。

表2.5按照优先级顺序列出了所有的操作符。同一行中的操作符,具有相同的优先级。

表2.5 操作符优先级

<div style="text-align: center">
 <img src="https://yqfile.alicdn.com/cd6a57893da6f4d2cfa38f0e103022547265987a.png" >
</div>

注意,圆括号具有最高的优先级。圆括号也可以使得表达式更为清晰。例如,考虑如下的代码:

int x = 5;
int y = 5;
boolean z = x * 5 == y + 20;

比较之后的z值为真。然而,这个表达式还远不够清晰,你可以使用圆括号重新编写最后一行。

boolean z = (x * 5) == (y + 20);

这并不会改变结果,因为*和+拥有比==更高的优先级,但是,这会使得表达式更为清晰。

**2.8.11 提升**
一些一元操作符(例如+、−和~)和二元操作符(例如,+、−、*和/),会导致自动提升(automatic promotion),例如,演变为一种更宽的类型,如从byte类型到int类型。考虑如下的代码:

byte x = 5;
byte y = -x; // error

第2行会莫名其妙地导致一个错误,即便一个byte类型可以容纳-5。其原因是,一元操作符-导致-x的结果提升为int。要修正这个问题,要么将y修改为int,要么像下面这样执行一次显式的收窄转换:

byte x = 5;
byte y = (byte) –x;

对于一元操作符来说,如果操作数的类型是byte、short或char,结果提升为int类型。

对于二元操作符来说,提升规则如下:

如果任何的操作数类型为byte或short,那么,两个操作数都将转换为int,并且结果会是一个int。
如果任何的操作数的类型为double,那么,另一个操作数转换为double,并且结果将会是一个double。
如果任何的操作数的类型为float,那么,另一个操作数转换为float,并且结果将会是一个float。
如果任何的操作数的类型是long,那么,另一个操作数转换为long,并且结果将会是一个long。
例如,如下的代码将会导致一个编译错误:

short x = 200;
short y = 400;
short z = x + y;

可以通过将z修改为int,或者对x+y执行一次显式的收窄转换,从而修正这个问题。

short z = (short) (x + y);

相关文章
|
6天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
52 13
|
14天前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
40 19
|
14天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
41 14
|
11天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
44 10
|
5天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
41 2
|
17天前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
15天前
|
XML 存储 Java
探索安卓开发之旅:从新手到专家
在数字时代,掌握安卓应用开发技能是进入IT行业的关键。本文将引导读者从零基础开始,逐步深入安卓开发的世界,通过实际案例和代码示例,展示如何构建自己的第一个安卓应用。我们将探讨基本概念、开发工具设置、用户界面设计、数据处理以及发布应用的全过程。无论你是编程新手还是有一定基础的开发者,这篇文章都将为你提供宝贵的知识和技能,帮助你在安卓开发的道路上迈出坚实的步伐。
29 5
|
14天前
|
开发框架 Android开发 iOS开发
安卓与iOS开发中的跨平台策略:一次编码,多平台部署
在移动应用开发的广阔天地中,安卓和iOS两大阵营各占一方。随着技术的发展,跨平台开发框架应运而生,它们承诺着“一次编码,到处运行”的便捷。本文将深入探讨跨平台开发的现状、挑战以及未来趋势,同时通过代码示例揭示跨平台工具的实际运用。
|
15天前
|
XML 搜索推荐 前端开发
安卓开发中的自定义视图:打造个性化UI组件
在安卓应用开发中,自定义视图是一种强大的工具,它允许开发者创造独一无二的用户界面元素,从而提升应用的外观和用户体验。本文将通过一个简单的自定义视图示例,引导你了解如何在安卓项目中实现自定义组件,并探讨其背后的技术原理。我们将从基础的View类讲起,逐步深入到绘图、事件处理以及性能优化等方面。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的见解和技巧。
|
14天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。