入门篇-其之六-Java运算符(中)
祝所有程序员,1024节日快乐!!!
一、自增/自减运算符
假设有一个变量intValue
的值为10,如果想让这个值加1,有哪些方式?
首先,我们可以使用最原始的方式:
int intValue = 10;
intValue = intValue + 1;
或者使用赋值运算符+=
操作:
int intValue = 10;
intValue += 1;
正如这一节的标题名称自增/自减运算符,我们可以使用自增运算符来解决上述的问题。
1.1 自增/自减运算符的基本使用
自增运算符使用变量名++(也叫后缀自增,因为++
在变量名后面)或者++变量名(也叫前缀自增,因为++
在变量名前面)的方式表示,二者最终都会将变量的值加1。
同理,自减运算符使用变量名--(也叫后缀自减,因为--
在变量名前面)或者--变量名(也叫前缀自减,因为--
在变量名前面)的方式表示,二者最终都会将变量的值减1。
以下是使用自增运算符解决上述问题的代码案例:
/**
* 自增自减运算符
*
* @author iCode504
* @date 2023-10-11 7:38
*/
public class IncrementAndDecrementOperators {
public static void main(String[] args) {
// 后缀自增i++和前缀自增++i简单使用
int intValue1 = 1;
intValue1++;
int intValue2 = 1;
++intValue2;
System.out.println("intValue1 = " + intValue1);
System.out.println("intValue2 = " + intValue2);
// 后缀自减i--和前缀自减--i简单使用
int intValue3 = 2;
intValue3--;
int intValue4 = 2;
--intValue4;
System.out.println("intValue3 = " + intValue3);
System.out.println("intValue4 = " + intValue4);
}
}
运行结果:
i++
或者++i
二者执行完表达式计算以后,i
的值自增1(同理,i--
或--i
得到的结果是i
自减1)。
1.2 前缀自增(减)和后缀自增(减)的区别
后缀自增i++
,先返回变量i
的当前值,运算完成后再将i
增加1。例如:j = i++ * 2
,此时右侧表达式计算时得到的是当前i
的值,在右侧表达式运算完成后,i
再自增1。
前缀自增++i
,先将i
的值增加1,然后返回变量i
的当前值。例如:j = ++i * 2
,此时右侧表达式计算时得到的是i
加1之后的值,在右侧表达式运算完成后,i
的值也就是前面自增1的结果。
接下来我们使用代码来测试一下:
/**
* i++和++i的区别
*
* @author iCode504
* @date 2023-10-16 22:39
*/
public class IncrementAndDecrementOperators1 {
public static void main(String[] args) {
int intValue1 = 10;
int intValue2 = 10;
int intValue3 = 10;
int intValue4 = 10;
int result1 = intValue1++;
int result2 = ++intValue2;
System.out.println("result1 = " + result1);
System.out.println("result2 = " + result2);
// 执行完赋值操作后,两个变量值最后都会自增1,此时得到的结果都是11
System.out.println("intValue1 = " + intValue1);
System.out.println("intValue2 = " + intValue2);
int result3 = intValue3++ * 2; // 计算时先赋值为intValue3的值,计算完成后intValue3的值自增1
int result4 = ++intValue4 * 2; // 计算时先将intValue4的值自增1,计算完成后将自增的值赋值给intValue4
System.out.println("result3 = " + result3);
System.out.println("result4 = " + result4);
}
}
运行结果:
关于i++
和++i
在字节码层面的区别,请查看这篇文章:点我查看
二、比较运算符
和数学学过的一样,Java的比较运算符有如下:大于>
,小于<
,等于==
,大于等于>=
,小于等于<=
,不等于!=
。
比较运算符得到的结果是布尔类型的值,即true
或false
。
/**
* 比较运算符的使用
*
* @author iCode504
* @date 2023-10-11 23:05
*/
public class ComparisonOperator {
public static void main(String[] args) {
int intValue1 = 30;
int intValue2 = 20;
System.out.println("intValue1 > intValue2: " + (intValue1 > intValue2)); // > 大于
System.out.println("intValue1 < intValue2: " + (intValue1 < intValue2)); // < 小于
System.out.println("intValue1 == intValue2: " + (intValue1 == intValue2)); // == 等于
System.out.println("intValue1 != intValue2 = " + (intValue1 != intValue2)); // != 不等于
System.out.println("intValue1 >= intValue2: " + (intValue1 >= intValue2)); // >= 大于等于
System.out.println("intValue1 <= intValue2: " + (intValue1 <= intValue2)); // <= 小于等于
}
}
运行结果:
三、逻辑运算符
逻辑运算符只能用在布尔值或者计算结果是布尔值的表达式(例如:比较运算符得到的结果就是布尔值)。
3.1 逻辑与、逻辑或运算符
短路与使用&&
表示,格式是:布尔表达式1 && 布尔表达式2。如果&&
两侧得到的结果都是true
,那么得到的结果也是true
,否则其他情况均为false
。
短路或使用||
表示,格式是:布尔表达式1 || 布尔表达式2。如果||
只要有一侧为true
,那么得到的结果是true
,如果两侧结果都是false
,那么得到的结果也是false
。
以下是示例代码:
/**
* 短路与&& 短路或|| 的使用
*
* @author iCode504
* @date 2023-10-16 22:24
*/
public class LogicOperators1 {
public static void main(String[] args) {
boolean result1 = 40 != 20;
boolean result2 = 20 > 5;
boolean result3 = 30 > 40;
System.out.println("计算结果");
System.out.println("result1 = " + result1);
System.out.println("result2 = " + result2);
System.out.println("result3 = " + result3);
System.out.println("使用短路与&& 短路或|| 的运算结果: ");
System.out.println("result1 && result2 = " + (result1 && result2));
System.out.println("result1 && result3 = " + (result1 && result3));
System.out.println("result2 && result3 = " + (result2 && result3));
System.out.println("result1 || result2 = " + (result1 || result2));
System.out.println("result1 || result3 = " + (result1 || result3));
System.out.println("result2 || result3 = " + (result2 || result3));
}
}
运行结果:
运行结果符合我们的预期和上述的说明。
3.2 逻辑非运算符
非运算符使用!
表示,格式为:!布尔值
或者!布尔表达式
。
非运算符的作用是将得到的布尔值取反,例如:!true
的结果是false
,同理,!false
的结果是true
,以下是非运算符在代码中的使用:
/**
* 逻辑非运算符! 的使用
*
* @author iCode504
* @date 2023-10-16 22:13
*/
public class LogicOperators2 {
public static void main(String[] args) {
boolean result1 = 20 >= 30;
boolean result2 = 40 != 20;
System.out.println("正常结果: ");
System.out.println("result1 = " + result1);
System.out.println("result2 = " + result2);
System.out.println("取非运算符!得到的结果");
System.out.println("!result1 = " + !result1);
System.out.println("!result2 = " + !result2);
}
}
运行结果:
从结果中我们可以看出,运算结果如果为true
,加上非运算符,得到的结果正好相反,为false
。同理,如果运算结果为false
,取非得到的结果是true
。
四、位运算符(了解即可)
位运算符主要是针对整型数字的二进制进行运算。在二进制的位运算中,1表示真,0表示假。
4.1 位与、位或、异或运算符
位运算符主要包含如下的运算符:
符号 | 名称 | 说明 |
---|---|---|
& |
位与运算符 | 如果相同位两个二进制数都为1,则结果为1;反之,结果为0。 |
` | ` | 位或运算符 |
^ |
异或运算符 | 如果相同位两个二进制数相同,则结果为0;反之,结果为1。 |
~ |
非运算符 | 一元运算符,将每一位的二进制数由1变0,由0变1。 |
看完上述说明可能还是一头雾水,接下来以具体案例来说明它们是如何使用的。
假设有两个int
类型的整数,第一个值为8,另一个值是6,将其转换成32位(因为int
本身就是32位)的二进制整数为:
由于前24位(未标黄部分)都是0,为了直观展示上述运算符的运算过程,在后续计算中默认省略前24位:
按照位与&
的运算规则,在相同位上两个二进制数的值都为1,则结果为1,否则其他情况都为0,那么此时的运算过程为:
得到的结果为:
\]
转换成十进制的结果就是0,8 & 6
的结果为0。
同理,按照位或|
的规则,如果相同位两个二进制数都为0,则结果为0;反之,结果为1。此时的运算过程为:
得到的结果:
\]
转换成十进制就是14,因此8 | 6
的运算结果是14。
根据异或运算符的规则:如果相同位两个二进制数相同,则结果为0;反之,结果为1。此时的运算过程为:
得到的结果:
\]
转换成十进制是14,因此8 ^ 6
得到的结果是14。
4.2 非运算符
此时我们再观察完整的8和6的二进制数(32位)
按照非运算符~
的规定,将每一位的二进制数由1变0,由0变1。此时~8
会转换成如下的形式:
二进制的第一位表示正负号,0表示正号,1表示负号,并且不参与运算。此时从~8
得到的二进制数来看,未来转换成十进制数字也是负数。
负数的二进制表示:除符号位以外,其他位取反操作(0变成1,1变成0),然后再加1以补码的方式表示。
此时~8
的结果就是补码,我们需要对上述操作进行逆向操作。
首先,将二进制数减1,得到如下结果(反码):
再将反码还原(1变成0,0变成1),得到如下结果:
此时除第一位是负数以外,再将得到的结果转换成十进制数为-9
,因此~8
的结果是-9
。
同理,~6
的结果是-7
我们使用代码来检测一下上述运算结果:
/**
* 位运算符 & | ~的使用
*
* @author iCode504
* @date 2023-10-13 6:09
*/
public class ByteOperators1 {
public static void main(String[] args) {
int intValue1 = 8;
int intValue2 = 6;
int result1 = intValue1 & intValue2;
System.out.println("intValue1 & intValue2 = " + result1);
int result2 = intValue1 | intValue2;
System.out.println("intValue1 | intValue2 = " + result2);
int result3 = ~intValue1;
int result4 = ~intValue2;
System.out.println("~intValue1 = " + result3);
System.out.println("~intValue2 = " + result4);
}
}
运行结果:
4.3 移位运算符
移位运算符的主要是针对二进制数向左或者向右移动n位。其中<<
称作有符号左移运算符,>>
称作有符号右移运算符。
以有符号左移运算符为例,它的使用格式是:操作数 << 左移位数,例如:3 << 4
的含义是将3的二进制数向左移动4位(第1位符号位除外)。以下是它的运算过程:
将3转换成32位二进制数,如下图所示:
移动原则是:向左移,最左边多出的位数舍去,右侧空缺使用0来补缺(负数使用1来补缺)。同理,向右移,最右边多出的位数舍去,左侧空缺使用0来补缺(负数使用1来补缺)。
3向左移动4位以后的情况如下图:
按照上述规则,将左侧多出的4位舍去,右侧空缺位置使用0补上,此时得到的结果是:
将得到的结果转换成十进制数是:
\]
因此:3 << 4
得到的结果是48。
同理,右移运算符的使用格式是:操作数 >> 右移位数,例如:-20 >> 3
的含义是将-20的二进制数向右移动3位(第1位符号位除外)。以下是运算过程:
首先将-20转换成二进制形式表示(负数使用补码表示并参与计算):
-20向右移动3位以后的情况如下图所示:
此时空缺位使用1来补位(因为-20是负数),多余位舍去,得到如下的结果:
此时将负数的补码转换成原码的形式表示(原码和补码的知识可以查看这篇文章的原码、反码、补码:点我查看):
此时我们将原码转换成十进制表示:
\]
因此-20 >> 3
得到的结果是-3。
前面我们提到的都是有符号移位。在Java中,还有一个无符号右移运算符,使用>>>
表示,格式是:操作数 >>> 向右移动数。
无符号右移运算符在向右移动时符号位和其他数字都参与移动。此时空缺位使用0来补齐即可。
这次我们让-20无符号右移3位,移动后的情况如下:
空缺位使用0补齐,多余位舍掉后的结果如下图:
使用计算器转换为十进制数字得到的结果如下图:
我们使用代码来验证一下上述推算过程得到的结果是否符合我们的预期:
/**
* 位运算符 >> << 和 >>>的使用
*
* @author iCode504
* @date 2023-10-16 7:31
*/
public class ByteOperators2 {
public static void main(String[] args) {
int result1 = 3 << 4;
int result2 = -20 >> 3;
int result3 = -20 >>> 3;
System.out.println("3 << 4 = " + result1);
System.out.println("-20 >> 3 = " + result2);
System.out.println("-20 >>> 3 = " + result3);
}
}
运行结果:
使用位运算符主要是针对整型数据的二进制值进行操作,由于位运算符直接操作二进制数值,执行效率非常高,远超普通的四则运算。但是为什么在日常开发中我们很少使用位运算符呢?
1. 首先,位运算符虽然执行效率非常高,但是可读性较差,容易让人困惑。例如:前面的-20 >> 3
的例子虽然在表面上是让-20向右移动3位,但是里面涉及到的过程是十分复杂的(负数由补码到反码,反码到补码就能让人焦头烂额)。
2. 大多数情况下我们都不需要直接操作二进制值。日常开发中,我们是直接针对数据做进一步处理即可,无需额外转换成二进制数据。
3. 位运算符只有在计算机底层开发或者在性能等关键领域开发会用到。
入门篇-其之六-Java运算符(中)的更多相关文章
- C#入门篇-4:使用运算符
using System; using System.Text; using System.Collections; using System.Collections.Generic; using S ...
- JS基础入门篇(七)—运算符
1.算术运算符 1.算术运算符 算术运算符:+ ,- ,* ,/ ,%(取余) ,++ ,-- . 重点:++和--前置和后置的区别. 1.1 前置 ++ 和 后置 ++ 前置++:先自增值,再使用值 ...
- 前端向后台的华丽转身 — PHP入门篇
三个月就这么悄悄溜走了,本K对于前端虽然有了一定的认识,但对一些方面还是处于一种比较萌币的状态,就在这种萌币状态下,本K又跟着大神浩开始了后台语言-PHP语言的学习.PHP的学习对于学过其他语言的人来 ...
- Java总结篇系列:Java多线程(三)
本文主要接着前面多线程的两篇文章总结Java多线程中的线程安全问题. 一.一个典型的Java线程安全例子 public class ThreadTest { public static void ma ...
- Swift入门篇-swift简介
潜水博客园很多年,闲来无事,聊一下自己的经历,语文不好(如有什么错别字,请您在下评论)望您谅解,没有上过什么学的 在前期 ios入门篇 -hello Word(1) 文章中介绍我这半年准备写一些ios ...
- Java中的IO流 - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的IO流-入门篇>,希望对大家有帮助,谢谢 由于Java的IO类有很多,这就导致我刚开始学的时候,感觉很乱,每次用到都是上网搜,结果 ...
- Java中的集合List - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合List - 入门篇>,希望对大家有帮助,谢谢 简介 说实话,Java中的集合有很多种,但是这里作为入门级别,先简单介绍第一种 ...
- Java中的映射Map - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的映射Map - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,这里开始简单介绍下映射Map,相关类如下图所示 正 ...
- Java中的集合Set - 入门篇
前言 大家好啊,我是汤圆,今天给大家带来的是<Java中的集合Set - 入门篇>,希望对大家有帮助,谢谢 简介 前面介绍了集合List,映射Map,最后再简单介绍下集合Set,相关类如下 ...
- 《Java从入门到放弃》入门篇:hibernate中的多表对应关系
hibernate中的对应关系其实就是数据库中表的对应关系, 就跟某些电影中的某些场景是一样一样滴. 比如可以是一男一女,还可以是一男多女, 更可以是多男一女,最后最后最后还可以是多男多女!!! 有些 ...
随机推荐
- 深度解读AIGC存储解决方案
5月26日,2023数据基础设施技术峰会在苏州举办,腾讯云首席存储技术专家温涛受邀出席并分享了腾讯云领先的存储技术在AIGC场景中的应用,通过对AIGC业务流程和场景的提炼,从内容生成.内容审核和内容 ...
- 我和ChatGPT聊数字人
近期,聊天机器人ChatGPT火了,写诗写文写代码,才艺狠狠拉满. 面对如此"会聊"的ChatGPT,很多人好奇相同的问题提问ChatGPT和真人,会有什么样的结果? 于是我们 ...
- Rust 学习笔记:快速上手篇
Rust 学习笔记:快速上手篇 这篇学习笔记将用于记录本人在快速上手 Rust 编程语言时所记录的学习心得与代码实例.为此,我会在本笔记库项目的Programming/LanguageStudy/目录 ...
- 上班第一天 Android 环境配置
其实是昨天把大概 回归Android开发第一天 学会查 然后等待 反正我是不希望以后再查了 写出来吧 去谷歌那边把android studio下载下来 更新jdk版本(与传统的java开发不同 高版本 ...
- Cilium系列-1-Cilium特色 功能及适用场景
系列文章 Cilium 系列文章 Cilium 简介 Cilium 是一个开源的云原生解决方案,用于提供.保护(安全功能)和观察(监控功能)工作负载之间的网络连接,由革命性的内核技术 eBPF 提供动 ...
- 【持续更新】C/C++ 踩坑记录(一)
未定义行为之 NULL dereference 下面这段代码中 is_valid() 解引用了空指针 str,我们的直觉是编译运行后将迎来 SIGSEGV,然而事情并非所期望的那样. /* * ub_ ...
- Linux 使用grep过滤字符串中的指定内容
命令示例:echo port 1234 123 | grep -oP 'port\s+\K\d+' 返回: 1234 这条命令使用 grep 工具来在文本中查找 "Port " 后 ...
- Linux 修改文本dos/unix 格式
使用 vi 命令打开文件,使用 :set ff 查看格式 如果显示dos,可使用 :set ff=unix 修改 pem 证书,使用 cat xx.key xx.crt DigiCertCA.crt ...
- VUE3、ElementPlus 重构若依vue2 表单构建功能
Vue3 + ElementPlus + Vite 重构 若依Vue2 表单构建功能 若依官方的Vue3 版本发布已经有段时间了,就是这个表单构建功能一直没有安排计划去适配到Vue3! 前段时间公司需 ...
- Visual Studio常用快捷键(附带免费PDF)
前言 对于开发者而言,熟悉快捷键的使用,能够起到事半功倍的作用,提高工作效率.以下是我整理的一份Visual Studio常用快捷键清单,希望能够帮助到你. 常用快捷方式 快捷键 功能 Ctrl + ...