《21天学通Java(第7版)》—— 2.5 表达式和运算符

简介: int x = 3; int y = x; int z = x * y; 这3条语句都是表达式——它们提供了可被赋给变量的值。第1条语句将字面量3赋给变量x。第2条语句将变量x的值赋给变量y。在第3条语句中,乘法运算符*用来将x和y相乘,结果存储在变量z中。

本节书摘来异步社区《21天学通Java(第7版)》一书中的第2章,第2.5节,作者: 【美】Rogers Cadenhead(罗格斯 卡登海德),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.5 表达式和运算符

表达式是一条能够提供值的语句。最常见的是数学表达式,如下面的例子所示:

int x = 3;
int y = x;
int z = x * y;

这3条语句都是表达式——它们提供了可被赋给变量的值。第1条语句将字面量3赋给变量x。第2条语句将变量x的值赋给变量y。在第3条语句中,乘法运算符*用来将x和y相乘,结果存储在变量z中。

表达式可以是变量、字面量和运算符的任何组合,也可以是方法调用,因为方法能够将一个值返回给调用它的类或对象。

您知道,表达式所提供的值称为返回值。在Java程序中,可将这个值赋给变量或以其他方式使用。

大多数Java中的表达式使用了运算符,如*。运算符是一些特殊符号,用于数学函数、赋值语句和逻辑比较。

2.5.1 算术运算符

在Java中,有5种用来完成基本算术运算的运算符,如表2.3所示。

6a82057bff8d2ebdb64093865a1bc368057076f4

每个运算符都有两个操作数,一边一个。减法运算符也可以用来对单个操作数求反,即将操作数与−1相乘。

使用除法时,要注意操作数的类型。如果将除法运算的结果存储在整型变量中,结果将向下取整,因为int类型不能处理浮点数。

例如,如果将结果存储在int变量中,则表达式31/9的结果为3。

使用运算符%的求模运算得到的是除法运算的余数。例如,31%9的结果是4,因为31被9除的余数是4。

很多针对整数的算术运算的结果为int值,而不管操作数是什么类型。处理其他数值类型,如浮点数或长整型时,应确保操作数的类型与所需结果的类型相同。

要创建的下一个项目是个Java类,它演示了如何使用Java执行简单的算术运算。为此,在NetBeans中新建一个空Java文件,将其命名为Weather并放在com.java21days包中,再在源代码编辑器中输入程序清单2.2所示的代码。输入完毕后选择菜单“文件”>“保存”将这个文件存盘。

程序清单2.2 源代码文件Weather.java

1: package com.java21days;
2:
3: public class Weather {
4:      public static void main(String[] arguments) {
5:           float fah = 86;
6:           System.out.println(fah + " degrees Fahrenheit is ...");
7:           // To convert Fahrenheit into Celsius
8:           // begin by subtracting 32
9:           fah = fah - 32;
10:          // Divide the answer by 9
11:          fah = fah / 9;
12:          // Multiply that answer by 5
13:          fah = fah * 5;
14:          System.out.println(fah + " degrees Celsius\n");
15:
16:          float cel = 33;
17:          System.out.println(cel + " degrees Celsius is ...");
18:          // To convert Celsius into Fahrenheit
19:          // begin by multiplying by 9
20:          cel = cel * 9;
21:          // Divide the answer by 5
22:          cel = cel / 5;
23:          // Add 32 to the answer
24:          cel = cel + 32;
25:          System.out.println(cel + " degrees Fahrenheit");
26:      }
27: }

选择菜单“运行”>“运行文件”运行该程序,它将生成如图2.2所示的输出。

439378d359f2b81c0a458e5e839e4322a5fc7c52

该Java应用程序的第5~14行使用算数运算符将华氏温度转换为摄氏温度。

第5行:声明浮点变量fah,并将其初始化为86。
第6行:显示fah的当前值。
第7行:第一个注释,解释了该程序的功能。这些注释将被Java编译器忽略。
第9行:将fah的值减去32。
第11行:将fah的值除以9。
第13行:将fah的值乘以5。
第14行:将fah的值转换为摄氏温度后,再次显示它。
第16~25行与此类似,但执行相反的转换——将摄氏温度转换为华氏温度。

2.5.2 再谈赋值

给变量赋值的语句是一个表达式,因为它生成一个值。因此,可以下面这种不同寻常的方式将赋值语句连在一起:

x = y = z = 7;
在这条语句中,所有3个变量(x、y和z)的值最后都为7。

在赋值之前,将首先计算赋值表达式的右边。因此,可以这样使用表达式语句:

int x = 5;
x = x + 2;

在表达式x = x + 2中,首先计算x+2;然后将结果(7)赋给变量x。

在编程中,使用表达式来修改变量的值是一项常见的任务。有几个专门用于这方面的运算符。

表2.4列出了这些赋值运算符及等效的表达式。

f64c433fc9166209d21a8ade88b81f2a55e52efd

这些简化的赋值运算符与它们所代表的更长的赋值语句等效。然而,如果赋值语句的一边是复杂的表达式,将出现不再等效的情况。例如,如果x等于20,y等于5,下面两条语句的结果将不同:

x = x / y + 5;
x /= y + 5;

其中第一条语句导致x的值为9,而第二条语句导致x的值为2。有疑问时,应使用多条赋值语句来简化表达式,而不要使用简化的运算符。
2.5.3 递增和递减运算符
另一种常见的编程任务将整型变量加1或减1。有专门用于完成这种运算的运算符:递增和递减运算符。对变量做递增运算意味着将它的值加1,做递减运算意味着将它的值减1。

递增运算符是++,递减运算符是−−。这些运算符位于变量名的前面或后面,如下所示:

int x = 7;
x++;

其中语句x++将变量x的值从7增加到8。

递增和递减运算符可放在变量名的前面或后面,这将影响表达式的结果。

如果递增和递减运算符位于变量名前面,则被称为前缀运算符;如果位于变量名后面,则被称为后缀运算符。

在简单表达式(如counts--;)中,无论使用前缀还是后缀运算符,结果都相同,因此它们可以互换。然而,当递增和递减运算符被用于更复杂的表达式中时,选择前缀还是后缀运算符就至关重要。

请看下面的代码:

int x, y, z;
x = 42;
y = x++;
z = ++x;

上述3个表达式由于前缀和后缀运算符的差别而产生完全不同的结果。

使用后缀运算符时,先使用变量的值,再将变量递增或递减。因此,在y = x++中,先将x的值赋给y,再将x的值加1。

使用前缀运算符时,先将变量递增或递减,再使用变量的值。例如,在z = ++x中,先将x的值加1,再将x的值赋给z。

上述代码的最终结果是,y等于42,z等于44,x等于44。

如果对此还不清楚,下面的例子再次通过注释描述了每一步的情况:

int x, y, z; // x, y, and z are declared
x = 42;        // x is given the value 42
y = x++;       // y is given x's value (42) before it is incremented
                     // and x is then incremented to 43
z = ++x;        // x is incremented to 44, and z is given x's value

在特别复杂的表达式中使用递增和递减运算符时,很可能得到意外的结果。“在x自增之前将x的值赋给y”这一概念不再完全正确,因为Java总是先计算表达式右边的内容,然后再把结果赋给表达式左边的变量。Java在处理表达式之前会存储一些值,以便后缀运算符能够像本节介绍的那样工作。当包含前缀和后缀运算符的复杂表达式的结果不同于您的期望时,请将该表达式拆成多个语句,以简化它。

2.5.4 比较运算符

Java有几种可用于对变量之间、变量和字面量(或其他类型的信息)之间进行比较的运算符。

这些运算符用于返回布尔值(true或false)的表达式,表达式的返回值取决于比较的结果是真还是假。表2.5列出了这些比较运算符。

0d1207d7a747f0b1039989d21622fb37436240a7

下面的例子演示了比较运算符的用法:

boolean isHip;
int age = 37;
isHip = age < 25;

表达式age<25的结果为true还是false取决于age的值。由于这里的age为37(比25大),因此isHip为布尔值false。

2.5.5 逻辑运算符

结果为布尔值的表达式(如比较运算)可以被组合成更加复杂的表达式。这是通过逻辑运算符来实现的,逻辑运算符用于逻辑组合:AND、OR、XOR和逻辑NOT。

对于AND组合,可使用逻辑运算符&或&&。当两个布尔表达式通过&或&&组合在一起后,仅当两个布尔表达式都为真时,整个表达式的结果才为true。

请看下面的例子:

boolean extraLife = (score > 75000) & (playerLives < 10);
这个表达式将两个比较表达式(score > 75000和playerLives <10)组合在一起。如果这两个表达式都为真,则true被赋给变量extraLife;在其他情况下,false被赋给extraLife。

&和&&之间的差别在于Java对组合表达式所做的工作量。如果使用&,则不管什么情况下,&两边的表达式都将被计算;如果使用&&,则当左边的表达式为false时,将不计算右边的表达式。

因此,&&的效率更高,因为它不做不必要的工作。在前面的示例中,如果score不比75000大,就根本不需要考虑playLives是否小于10。

对于OR组合,可使用逻辑运算符|或||。如果运算符两边的任何一个布尔表达式为真,则组合表达式的结果为true。

请看下述示例:

boolean extralife = (score > 75000) || (playerLevel == 0);
该表达式合并了两个比较表达式:score > 75000和playerLevel = = 0。只要这两个表达式中的任何一个为真,则true被赋给变量extraLife;仅当这两个表达式都是false时,false才被赋给extraLife。

注意,这里使用的是||,而不是|。因此,如果score > 75000为true,则extraLife将被设置成true,而根本不会计算第二个表达式。

用于XOR合并的逻辑运算符只有一个:^。仅当被合并的两个布尔表达式的值相反时,整个表达式的结果才为true;如果两个表达式都是true或都是false,则^运算符的结果为false。

NOT组合使用逻辑运算符!,后面跟一个表达式。它对布尔表达式的值求反,这与用负号来改变数字的符号相同。例如,如果age<25的结果为true,则!(age<25)的结果将为false。

首次见到这些逻辑运算符时,可能觉得它们完全不符合逻辑。在本周余下的课程中,您将大量地使用它们,尤其是在第5章。

2.5.6 运算符优先级

当表达式中有多个运算符时,Java有一套优先级用来判断运算符的执行顺序。在许多情况下,优先级决定了整个表达式的最终值。

例如,请看下面的表达式:

y = 6 + 4 / 2;
变量y的值为5还是8取决于哪个算术运算先被处理。如果先计算表达式6+4,则y的值为5;否则为8。

通常,从先到后的顺序如下:

  • 1.递增和递减运算;
  • 2.算术运算;
  • 3.比较运算;
  • 4.逻辑运算;
  • 5.赋值运算。

如果两个运算的优先级相同,则左边的比右边的先被处理。表2.6列出了Java中众多运算符的优先级。排在越前面的运算符的优先级越高。

56c11f8b7664cfc9ef8070b116ed28e35c028815 b6d92f63977905449e793d36e148762da045e4c6

表2.6中的多个运算符都将在本周后面的课程中介绍。

回过头来看表达式y =6 + 4 / 2。表2.6表明,除法先于加法计算,因此y的值为8。

要改变表达式求值的顺序,可以用圆括号将需要先计算的表达式括起。可以嵌套圆括号以确保按所需的顺序对表达式进行求值——最里边的圆括号内的表达式最先被计算。

下述表达式的结果为5:

y = (6 + 4) / 2
因为先计算6 + 4,得到10,然后再除以2,最后的结果为5。

圆括号还可以提高表达式的可读性。如果不能一眼看出表达式的优先级,可以添加圆括号来强制转换为希望的优先级,使语句更容易理解。

相关文章
|
6月前
|
Java Go 开发工具
【Java】(4)五种运算符的说明(&&、||、>=、>、<=、<)、4种控制语句(if、for、while、dowhile)、输入和输出说明
扩展类的赋值运算符不改变运算结果类型,假设最初这个变量的的类型byte类型,无论怎么进行加或追减,最终该变量的数据类型还是byte类型。注:一个表达式中有多个运算符,运算符有优先级,不确定的加小括号,优先级得到提升。当布尔表达式的结果是false的时候,选择表达式2作为整个表达式的执行结果。当布尔表达式的结果是true的时候,选择表达式1作为整个表达式的执行结果。当用户输入的时候,并且最终敲回车键的时候,键入的信息会自动赋值给a。并且,连接运算之后的结果还是一个字符串类型。表达式1 : 表达式2。
230 1
|
8月前
|
Java 编译器 API
Java Lambda表达式与函数式编程入门
Lambda表达式是Java 8引入的重要特性,简化了函数式编程的实现方式。它通过简洁的语法替代传统的匿名内部类,使代码更清晰、易读。本文深入讲解Lambda表达式的基本语法、函数式接口、方法引用等核心概念,并结合集合操作、线程处理、事件回调等实战案例,帮助开发者掌握现代Java编程技巧。同时,还解析了面试中高频出现的相关问题,助你深入理解其原理与应用场景。
|
8月前
|
存储 缓存 算法
Java数据类型与运算符深度解析
本文深入解析Java中容易混淆的基础知识,包括八大基本数据类型(如int、Integer)、自动装箱与拆箱机制,以及运算符(如&与&&)的使用区别。通过代码示例剖析内存布局、取值范围及常见陷阱,帮助开发者写出更高效、健壮的代码,并附有面试高频问题解析,夯实基础。
|
8月前
|
安全 Java API
Java中的Lambda表达式:简洁与功能的结合
Java中的Lambda表达式:简洁与功能的结合
525 211
|
8月前
|
安全 Java
Java中的Switch表达式:更简洁的多路分支
Java中的Switch表达式:更简洁的多路分支
647 211
|
8月前
|
Java 编译器
Java 17 Switch表达式:更简洁、更强大的流程控制
Java 17 Switch表达式:更简洁、更强大的流程控制
939 111
|
9月前
|
设计模式 数据采集 Java
Java正则表达式的基础知识,进阶至熟练掌握。
通过大量的练习来熟悉它们的识别模式、如何设计模式来解决实际问题,才能够逐步达到熟练掌握。更多的是通过实践、编写代码和解决真实问题来完善技能。在这方面,没有快速的捷径,唯有刻意练习和长时间的代码实践。
182 0
|
9月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
457 14
|
10月前
|
SQL JSON 安全
Java 8 + 中 Lambda 表达式与 Stream API 的应用解析
摘要:本文介绍了Java 8+核心新特性,包括Lambda表达式与Stream API的集合操作(如过滤统计)、函数式接口的自定义实现、Optional类的空值安全处理、接口默认方法与静态方法的扩展能力,以及Java 9模块化系统的组件管理。每个特性均配有典型应用场景和代码示例,如使用Stream统计字符串长度、Optional处理Map取值、模块化项目的依赖声明等,帮助开发者掌握现代Java的高效编程范式。(150字)
183 1
下一篇
开通oss服务