运算符就是对字面量或者变量进行操作的符号
运算符可以按照功能和操作数个数来进行分类
功能分类 | 运算符 |
---|---|
算术运算符(5个) | +、-、*、\、% |
自增自减运算符(2个) | ++、– |
赋值运算符(12个) | =、+=、-=、*=、=、%=、&=、|=、^=、<<=、>>=、>>>= |
比较运算符/关系运算符(6个) | >、>=、<、<=、==、!= |
逻辑运算符(6个) | &、|、^、!、&&、|| |
条件运算符(1个) | (布尔表达式)?结果1:结果2 |
位运算符(7个) | &、|、~、^、<<、>>、>>> |
lambda运算符 | -> |
分类 | 运算符 | 案例 |
---|---|---|
一元运算符/单目运算符 | 正号(+)、负号(-)、++、–、!、~ | i++、i–、 |
二元运算符/二目运算符 | +、-、*、\、%、>、>=、<、<=、==、!= | a+b、10>=8 |
三元运算符/三目运算符 | (布尔表达式)?结果1:结果2 | age>=18?“成年”:“未成年” |
表达式就是用运算符把字面量或者变量连接起来符合Java语法的式子就可以称为表达式
不同运算符连接的表达式的体现是不同类型的表达式
Operator.java演示运算符相关的概念:包括操作数、运算符、表达式
其中left + right就是一个算术表达式,因为+是算术运算符,而left和right就是操作数,表达式是由操作数和运算符组成的,操作数可以是字面量、变量或者其他表达式。
package net.ittimeline.java.core.foundational.operator;
/**
* 运算符和表达式
*
* @author tony [email protected]
* @version 2023/7/21 9:55
* @since Java17
*/
public class Operator {
public static void main(String[] args) {
//定义两个整数变量
int left = 10;
int right = 20;
/*
left + right就是一个算术表达式,因为+是算术运算符,而left和right就是操作数,表达式是由操作数和运算符构成的,操作数可以是字面量、变量或者其他表达式。
*/
//计算两个整数变量相加的结果赋值给result
int result = left + right;
System.out.println("result = " + result);
}
}
程序运行结果
如下表格汇总所有运算符的优先级,优先级的数字越大越会优先计算,其中括号的优先级是最高的。
优先级 | 运算符说明 | Java运算符 |
---|---|---|
1 | 括号 | () 、\[\] 、{} |
2 | 正负号 | + 、\- |
3 | 单元运算符 | ++ 、\-- 、~ 、! |
4 | 乘法、除法、求余 | \* 、/ 、% |
5 | 加法、减法 | + 、\- |
6 | 移位运算符 | << 、\>> 、\>>> |
7 | 关系运算符 | < 、<= 、\>= 、\> 、instanceof |
8 | 等价运算符 | \== 、!= |
9 | 按位与 | & |
10 | 按位异或 | ^ |
11 | 按位或 | | |
12 | 条件与 | && |
13 | 条件或 | || |
14 | 三元运算符 | ? : |
15 | 赋值运算符 | \= 、+= 、\-= 、\*= 、/= 、%= |
16 | 位赋值运算符 | &= 、|= 、<<= 、\>>= 、\>>>= |
由于Java的运算符比较多,要记住它们的优先级顺序比较困难,因此建议在开发项目中有以下建议。
不要太过于依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用括号()来表达式的执行顺序。
不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分解成几步来完成。
例如求三个数的最大值
没有分解步骤
int left =10;
int middle =20;
int right =30;
int max = (left > right ? left : right) > middle ? (left > right ? left : right) : middle;
分解步骤
int left =10;
int middle =20;
int right =30;
//先求两个数的最大值
int temp = left > right ? left : right;
//再求三个数的最大值
int max = temp > middle ? temp : middle;
结合性:表达式计算的方向,从右向左或者从左向右,大部分表达式计算的方向都是从左往右,但是赋值运算的结合性就是从右向左,结合性决定了优先级相等的情况下的计算顺序
int left, middle, right;
left = middle = right = 10;
算术运算符的结合性是从左向右
int result = 45 + 5 / 5 * 10;
Java支持5种算术运算符
加法(+)
减法(-)
乘法(*)
除法(/)被除数 / 除数 = 商数 求商数
取模/取余(%)被除数 / 除数 = 商数…余数 求余数
取模的应用场景
判断一个数A,是否可以被另外一个数B整除,如果A对B进行取模结果为0,那么就表示A能够被B整除
判断一个数字A是奇数还是偶数,也就是拿这个数A对2进行取模运算,如果结果为0表示这个数是一个偶数,否则就是一个奇数
ArithmeticOperatorLiteral.java演示算术运算符中的加法(+)、减法(-)、乘法(*)的使用,操作数都是字面量
package net.ittimeline.java.core.foundational.operator.arithmetic;
/**
* 算术运算符操作字面量
* @author tony [email protected]
* @version 2023/7/21 9:55
* @since Java17
*/
public class ArithmeticOperatorLiteral {
public static void main(String[] args) {
//加法(+)、减法(-)、乘法(*)的使用
System.out.println("3 + 5 = " + (3 + 5));
//格式化输出10 - 2 的计算结果
//第一个%d会被10替换
//第二个%d会被2替换
//第三个%d会被10-2的结果替换
System.out.printf("%d - %d = %d \n", 10, 2, (10 - 2));
System.out.printf("%d * %d = %d\n", 3, 5, (3 * 5));
//如果在计算的时候有小数参数,那么运算结果可能是不精确
//精确结果
System.out.println("1.1 + 1.1 = " + (1.1 + 1.1));
//不精确结果
System.out.println("1.1 + 1.01 = " + (1.1 + 1.01));
System.out.println("1.1 - 1.01 = " + (1.1 - 1.01));
}
}
程序运行结果
ArithmeticOperatorVariable.java演示算术运算符中的除法(/)和取余/取模(%)使用,操作数都是变量
package net.ittimeline.java.core.foundational.operator.arithmetic;
/**
* 算术运算符操作变量
*
* @author tony [email protected]
* @version 2023/7/20 7:20
* @since Java17
*/
public class ArithmeticOperatorVariable {
public static void main(String[] args) {
//除法的基本使用
int left = 12;
int right = 5;
被除数 / 除数 = 商数
//int和int运算结果还是int
int result = left / right;
//因此12 / 5 = 2
System.out.println("12 / 5 = " + result);
//格式化输出算术运算计算结果
//第一个%d会被left的值替换
//第二个%d会被right的值替换
//第三个%d会被result的值替换
System.out.printf("%d / %d = %d\n", left, right, result);
// 12 / 5 = 2
// 2 * 5 = 10
result = left / right * right;
//因此12 / 5 * 5 = 10
System.out.printf("%d / %d * %d = %d\n", left, right, right, result);
//取模的基本使用
//被除数 / 除数 = 商数...余数
// 12 / 5 = 2...2
//% 取模(取余) 结果就是2
result = left % right;
System.out.printf("%d %% %d = %d\n", left, right, result);
System.out.printf("%d %% %d = %d \n", 10, 3, 1);
}
}
程序运行结果
ArithmeticRemainderResultPositiveSignNegativeSign演示取模运算(%)结果的符号(正号、负号)和被除数的符号相同
package net.ittimeline.java.core.foundational.operator.arithmetic;
/**
* 算术运算符取模运算(%)结果的符号(正号、负号)和被除数的符号相同
*
* @author tony [email protected]
* @version 2023/7/21 10:16
* @since Java17
*/
public class ArithmeticRemainderResultPositiveSignNegativeSign {
public static void main(String[] args) {
//取模(取余)在实际开发中经常用来判断某个数能否整除另外一个数,比如判断number是否是偶数 number%2 == 0
/*****************取模/取余结果的符号(正负号)***********************/
//被除数 / 除数 = 商数...余数
//取模(求余数)的结果正负号和被除数是一样的
int left = -12;
int right = 5;
int result = left % right;
//格式化输出算术运算计算结果
//第一个%d会被left的值替换
//第二个%d会被right的值替换
//第三个%d会被result的值替换
System.out.printf("%d %% %d = %d\n", left, right, result);
left = 12;
right = -5;
result = left % right;
System.out.printf("%d %% %d = %d\n", left, right, result);
left = -12;
right = -5;
result = left % right;
System.out.printf("%d %% %d = %d\n", left, right, result);
}
}
程序运行结果
在使用加法(+)时可能会遇到以下三种情况
数字相加:如果+左右两边是数字就进行加法运算,数字在进行运算是,数据类型不一样是不能进行运算的,需要转成一样的才能运算。
字符串相加:如果+左右两边有一边是字符串,那么就进行字符串拼接运算并产生一个新的字符串,如果有多个+操作时,会从左到右逐个执行
字符相加:如果+左右两边都是是字符或者是字符+数字时,那么就按照字符的ASCII编码进行加法运算
ArithmeticOperatorAdd.java演示加法使用的三种情况
package net.ittimeline.java.core.foundational.operator.arithmetic;
/**
* 加法使用的三种情况
*
* @author tony [email protected]
* @version 2023/7/21 10:29
* @since Java17
*/
public class ArithmeticOperatorAdd {
public static void main(String[] args) {
//1.数字相加
int left = 10;
double right = 20.3;
//int和double进行运算 int会自动提升为double 结果类型是double类型
double result = left + right;
//result =30.3
System.out.println("result = " + result);
// 2. 字符串拼接
//第一个加法表示数字相加 因为加法左右两边都是数字
//第二个加法表示字符串拼接 因为加法右边有字符串,进行字符串拼接运算
System.out.println(1 + 99 + "年树人");
String name = "tony";
System.out.println("姓名是" + name);
int age = 30;
//age会被30替换
System.out.println("年龄是" + age + "岁");
double height = 180.00;
//height会被180.00替换
System.out.println("身高是" + height + "厘米");
// 3.字符相加
// a的ASCII码是97
System.out.println("1 + 'a' = " + (1 + 'a'));
//0的ASCII码是48
System.out.println("1 + '0' = " + (1 + '0'));
//A的ASCII码是65
System.out.println("1 + 'A' = " + (1 + 'A'));
//a的ASCII是97
//b的ASCII是98
System.out.println("'a' + 'b ' = " + ('a' + 'b'));
}
}
程序运行结果
ArithmeticOperatorWarning.java演示算术运算符的使用注意事项
当两个整数相除的时候只会保留整数部分,丢弃小数部分
如果想要保留整数相除运算结果的小数部分,可以使用强制类型转换将其中一个操作数转换成double或者是先将其中一个操作数乘以1.0后再运算
程序中只要有小数直接参与运算,那么运算的结果都有可能是不精确的
除数不能是0,否则会发生算术异常ArithmeticException
数值进行运算时,如果数据类型不一样不能运算,需要转成一样的才能运算
package net.ittimeline.java.core.foundational.operator.arithmetic;
/**
* 算术运算符的使用注意事项
*
* @author tony [email protected]
* @version 2023/7/21 10:47
* @since Java17
*/
public class ArithmeticOperatorWarning {
public static void main(String[] args) {
// 1. 当两个整数相除的时候只会保留整数部分,丢弃小数部分
System.out.println("5 / 3 = " + 5 / 3);
// 2.如果想要保留整数相除运算结果的小数部分,可以使用强制类型转换将其中一个操作数转换成double
System.out.println("(double)5 / 2 = " + (double) 5 / 2);
System.out.println("5 /(double) 2 = " + 5 / (double) 2);
//或者是先将其中一个操作数乘以1.0后再运算
System.out.println("5 * 1.0 / 2 = " + (5 * 1.0 / 2));
//3. 程序中只要有小数直接参与运算,那么运算的结果都有可能是不精确的
System.out.println("2.0 - 1.1 = " + (2.0 - 1.1));
//运算符是有优先级
//除法和乘法的优先级是相同的
//优先级相同的情况下看结合性
//结合性就是运算的方向,一般都是从左往右计算,赋值运算符除外
System.out.println("5 / 2 * 1.0 = " + 5 / 2 * 1.0);
//使用()提升运算符的优先级
//这里就意味着会先计算2*1.0
System.out.println("5 / (2 * 1.0) = " + 5 / (2 * 1.0));
// 4.除数不能是0,否则会发生算术异常ArithmeticException
// System.out.println("5 / 0 = " + 5 / 0);
//任何数处以0.0得到结果是Infinity
// 5 / 0.0 = Infinity
System.out.println("5 / 0.0 = " + 5 / 0.0);
// 0 / 0.0 = NaN ->Not a Number
System.out.println("0 / 0.0 = " + 0 / 0.0);
//5. 数值进行运算时,如果数据类型不一样不能运算,需要转成一样的才能运算
//5.0 + 5.0 * 97 = 5.0 + 485.0 = 490.0
double result = 5 + 10.0 / 2 * 'a';
System.out.println("5 + 10.0 / 2 * 'a' = " + result);
}
}
需求:键盘输入一个三位整数,将其拆分为个位、十位、百位后,打印在终端
分析:如何获取个位、十位、百位甚至是千位、万位
个位:数值/1%10
十位:数值/10%10
百位:数值/100%10
千位:数值/1000%10
万位:数值/10000%10
ArithmeticExample1NumericalValueSplit.java演示数值拆分需求的具体实现过程
package net.ittimeline.java.core.foundational.operator.arithmetic;
import java.util.Scanner;
/**
* 需求:键盘输入一个三位整数,将其拆分为个位、十位、百位后,打印在终端
*
* @author tony [email protected]
* @version 2023/7/21 10:18
* @since Java17
*/
public class ArithmeticOperatorExample1NumericalValueSplit {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
//提示用户从键盘输入一个整数
System.out.println("请输入一个三位整数");
//读取用户从键盘输入的整数赋值给number
int number = scanner.nextInt();
//获取整数的个位数、十位数、百位数
int unit = number / 1 % 10;
int decade = number / 10 % 10;
int hundred = number / 100 % 10;
System.out.printf("你输入的整数是%d\n其中个位数是%d 十位数是%d 百位数是%d\n", number, unit, decade, hundred);
scanner.close();
}
}
程序运行结果
需求:键盘输入一个三位整数,使用算术运算符实现三位整数反转,例如678反转以后就是876
分析:
参考数值拆分案例获取三位整数的个位、十位、百位
个位*100+十位*10+百位
ArithmeticOperatorExample2NumericalReversal.java演示整数反转需求的具体实现过程。
package net.ittimeline.java.core.foundational.operator.arithmetic;
import java.util.Scanner;
/**
* 需求:键盘输入一个三位整数,使用算术运算符实现三位整数反转,例如678反转以后就是876
*
* @author tony [email protected]
* @version 2023/7/21 10:58
* @since Java17
*/
public class ArithmeticOperatorExample2NumericalReversal {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
//提示用户从键盘输入一个整数
System.out.println("请输入一个三位整数");
//读取用户从键盘输入的整数赋值给number
int number = scanner.nextInt();
//获取整数的个位数、十位数、百位数
int unit = number / 1 % 10;
int decade = number / 10 % 10;
int hundred = number / 100 % 10;
int reversalNumber = unit * 100 + decade * 10 + hundred;
System.out.printf("你输入的整数是%d\n反转以后的结果是%d\n", number, reversalNumber);
}
}
程序运行结果
需求:根据用户输入的小时换算成多少天零多少小时,例如用户输入12小时换算成0天零12小时,用户输入89小时换算成3天零17小时
分析:
用户输入的小时/24计算的结果就是天数
用户输入的小时%24计算的结果就是小时
package net.ittimeline.java.core.foundational.operator.arithmetic;
import java.util.Scanner;
/**
* 需求:根据用户输入的小时换算成多少天零多少小时
*
* @author tony [email protected]
* @version 2023/7/21 11:26
* @since Java17
*/
public class ArithmeticOperatorExample3TimeConvert {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入小时数");
int inputHour = scanner.nextInt();
int days = inputHour / 24;
int remainHours = inputHour % 24;
System.out.printf("你输入的小时数是%d\n换算成%d天零%d小时\n", inputHour, days, remainHours);
scanner.close();
}
}
程序运行结果
需求:根据用户输入的秒数计算出对应的xx时xx分xx秒,假设用户输入的秒数是3800,3800秒对应的时间是1时3分20秒
分析:
关于时分秒换算的常识
1小时是60分钟,1分钟是60秒,一小时是3600秒
用户输入的秒数/3600计算的结果就是小时
用户输入的秒数%3600/60计算的结果就是分钟
用户输入的秒数%60计算的结果就是秒钟
ArithmeticOperatorExample3TimeConvert.java演示时间转换需求的具体实现过程
package net.ittimeline.java.core.foundational.operator.arithmetic;
import java.util.Scanner;
/**
* 需求:根据指定的秒数计算出对应的xx时xx分xx秒,假设用户输入的秒数是3800,3800秒对应的时间是1时3分20秒
*
* @author tony [email protected]
* @version 2023/7/21 11:07
* @since Java17
*/
public class ArithmeticOperatorExample3TimeConvert {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入待转换的秒数");
int inputSecond = scanner.nextInt();
//1.获取小时数
int hour = inputSecond / 3600;
//2. 获取分钟数
int minute = inputSecond % 3600 / 60;
// 3. 获取秒数
int second = inputSecond % 60;
System.out.printf("你输入的秒数是%d\n换算成%d时%d分%d秒\n", inputSecond, hour, minute, second);
scanner.close();
}
}
程序运行结果
自增运算符(++):用于将变量的值加1
自减运算符(–):用于将变量的值减1
自增自减运算符只能操作变量,不能操作字面量。
自增自减运算符只能有一个操作数,既可以放在变量的前面,也可以放在变量的后面
int number = 10;
++number;
int number = 10;
number--;
自增,自减运算符的应用场景
购物车加减商品
统计数量
自增、自减运算符有两种用法:
AutoIncrementOperatorUsage1.java演示自增运算符的单独使用
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 自增运算符的使用方式1:单独使用
*
* @author tony [email protected]
* @version 2023/7/21 11:58
* @since Java17
*/
public class AutoIncrementOperatorUsage1 {
public static void main(String[] args) {
int number = 10;
//把变量number的值自增1
++number;
//number等于11
System.out.println("前置++ number = " + number);
//把变量number的值自增1
number++;
//number等于12
System.out.println("后置++ number = " + number);
}
}
程序运行结果
AutoDecrementOperatorUsage1.java演示自减运算符的使用方式1:单独使用
package net.ittimeline.java.core.foundational.operator.autodecrement;
/**
* 自减运算符的使用方式1:单独使用
*
* @author tony [email protected]
* @version 2023/7/21 12:00
* @since Java17
*/
public class AutoDecrementOperatorUsage1 {
public static void main(String[] args) {
int number = 10;
//把变量number的值自减1
--number;
//number等于9
System.out.println("前置-- number = " + number);
//把变量number的值自减1
number--;
//number等于8
System.out.println("后置-- number = " + number);
}
}
程序运行结果
AutoIncrementOperatorUsage2.java演示自增运算符的使用方式2:参与计算
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 自增运算符的使用方式2:参与计算
*
* @author tony [email protected]
* @version 2023/7/21 12:06
* @since Java17
*/
public class AutoIncrementOperatorUsage2 {
public static void main(String[] args) {
int x = 10;
//后置++ 先用后加
//先把x赋值给y,然后再自增1
//赋值给y的值是自增之前的
//y等于10 x等于11
int y = x++;
//前置++ 先加后用
//先把x进行自增1,把自增之后的结果赋值给左边的变量
// z等于12 x等于12
int z = ++x;
//x等于12
System.out.println("x = " + x);
//y等于10
System.out.println("y = " + y);
//z等于12
System.out.println("z = " + z);
}
}
程序运行结果
AutoDecrementOperatorUsage2.java演示自减运算符的使用方式2:参与计算
package net.ittimeline.java.core.foundational.operator.autodecrement;
/**
* 自减运算符的使用方式2:参与计算
*
* @author tony [email protected]
* @version 2023/7/21 12:17
* @since Java17
*/
public class AutoDecrementOperatorUsage2 {
public static void main(String[] args) {
int x = 10;
//后置-- 先用后减
//先把x的值赋值给y,然后再自减1
//y等于10 x等于9
int y = x--;
//前置-- 先减后用
//x的值先自减1,再赋值给z
// x等于8,z等于
int z = --x;
//x等于8
System.out.println("x = " + x);
//y等于10
System.out.println("y = " + y);
//z等于8
System.out.println("z = " + z);
}
}
程序运行结果
如果是单独使用,前置++和后置++是相同的,它们都是让让变量自增1,而且源文件编译成字节码以后,后置++会编译成前置++
AutoIncrementOperatorAfterAddByteCode.java演示后置++
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 比较自增运算符单独使用时前置++和后置++的字节码文件
*
* @author tony [email protected]
* @version 2023/7/21 12:45
* @since Java17
*/
public class AutoIncrementOperatorAfterAddByteCode {
public static void main(String[] args) {
int number = 10;
//++number 和number++在字节码层面没有任何区别
//自增运算符单独使用时源码里面写number++ 编译之后的写法还是++number
number++;
System.out.println("number = " + number);
}
}
程序运行结果
运行AutoIncrementOperatorAfterAddByteCode.java后查看out目录下的字节码文件,该文件会由IntelliJ IDEA内置的反编译器编译
如果是参与运算:前置++:先自增1再参与运算,后置++:先运算再自增1
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 自增运算符前置++和后置++的区别
* 如果是单独使用:前置++和后置++是相同的,它们都是让让变量自增1
* 如果是参与运算:前置++:先自增1再参与运算,后置++:先参与运算再自增1
*
* @author tony [email protected]
* @version 2023/7/21 12:54
* @since Java17
*/
public class AutoIncrementOperatorBeforeAfterDiff {
public static void main(String[] args) {
int number = 10;
//1. 自增运算符单独使用
System.out.println("1. 自增运算符单独使用");
++number;
System.out.println("前置++ number = " + number);
number++;
System.out.println("后置++ number = " + number);
//2. 自增运算符参与运算
System.out.println("2. 自增运算符参与运算");
number = 10;
//后置++:先参与运算再自增1
//=表示赋值运算
//先将number的值赋值给result然后再自增1
int result = number++;
//result等于10
System.out.println("后置++:result = " + result);
//number等于11
System.out.println("后置++:number = " + number);
//前置++:先自增1再参与运算
//number先自增1 也就是12 再赋值给result
result = ++number;
//result等于12
System.out.println("前置++:result = " + result);
//number等于12
System.out.println("前置++:number = " + number);
//前置++和后置++组合使用
number = 10;
//先计算number++ 等于10 number等于11
//再计算++number 等于12 number等于12
//最后计算10+12等于22
result = number++ + ++number;
//result等于22
System.out.println("前置++和后置++组合使用:result = " + result);
}
}
程序运行结果
如果是单独使用,前置–和后置–是相同的,它们都是让变量自减1
如果是参与运算:前置++:先自减1再参与运算,后置++:先运算再自减1
package net.ittimeline.java.core.foundational.operator.autodecrement;
/**
* 前置--和后置--的区别
* 如果是单独使用,前置--和后置--是相同的,它们都是让变量自减1
* 如果是参与运算:前置++:先自减1再参与运算,后置++:先运算再自减1
*
* @author tony [email protected]
* @version 2023/7/21 13:19
* @since Java17
*/
public class AutoDecrementOperatorBeforeAfterDiff {
public static void main(String[] args) {
int number = 10;
//1. 自减运算符单独使用
System.out.println("1.自减运算符单独使用");
--number;
System.out.println("前置-- number = " + number);
number--;
System.out.println("后置-- number = " + number);
//2. 自减运算符参与运算
System.out.println("2.自减运算符参与运算");
number = 10;
//后置--:先参与运算再自减1
//=表示赋值运算
//先将number的值赋值给result然后再自减1
int result = number--;
//result等于10
System.out.println("后置--:result = " + result);
//number等于9
System.out.println("后置--:number = " + number);
//前置--:先自减1再参与运算
//number先自减1 也就是8 再赋值给result
result = --number;
//result等于8
System.out.println("前置--:result = " + result);
//number等于8
System.out.println("前置--:number = " + number);
//前置++和后置++组合使用
number = 10;
//先计算number-- 等于10 number等于9
//再计算--number 等于8 number等于8
//最后计算10+8等于18
result = number-- + --number;
//result等于18
System.out.println("前置--和后置--组合使用:result = " + result);
}
}
程序运行结果
自增运算符的自增1不会改变变量原有的数据类型,推荐使用
算术运算符的加1可能会改变变量原有数据类型
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 自增运算符的自增1和算术运算符的加1有什么区别
*
* @author tony [email protected]
* @version 2023/7/21 13:34
* @since Java17
*/
public class AutoIncrementOperatorArithmeticOperator {
public static void main(String[] args) {
byte byteVar = 10;
//byte和int进行加法运算结果是int 如果想要使用byte需要强制类型转换
byte byteResult = (byte) (byteVar + 1);
System.out.println("byteResult = " + byteResult);
//而自增运算符的自增1不会改变原有的数据类型
byteVar++;
System.out.println("byteVar = " + byteVar);
}
}
程序运行结果
需求:根据指定表达式计算i、j、k的值,但是实际开发中不要写太过于复杂的表达式,因为不利于程序的维护
package net.ittimeline.java.core.foundational.operator.autoincrement;
/**
* 自增运算符案例: 计算i、j、k的值
*
* @author tony [email protected]
* @version 2023/7/21 13:49
* @since Java17
*/
public class AutoIncrementOperatorExample {
public static void main(String[] args) {
int i = 1;
/*
1. 先执行自增运算,计算i的值:自增自减运算符优先级高于算术运算符
从左往右依次是 i++等于1 ,i等于2
++i等于3,i等于3
i++等于3 i等于4
i++ + ++i * i++ 等于1+ 3 * 3
2. 计算 i++ + ++i * i++表达式的值:算术运算符先乘除,后加减
1+3*3等于10
3.统计结果
i等于4
j等于10
*/
//实际开发不要写太过于复杂的表达式
int j = i++ + ++i * i++;
System.out.println("i = " + i);
System.out.println("j = " + j);
int k = 2;
/*
k等于2
k++等于2
k等于3
不过是将k++赋值给k 因此k=2
*/
k = k++;
System.out.println("k = " + k);
}
}
程序运行结果
根据指定表达式计算i、j、k的值,但是实际开发中不要写太过于复杂的表达式,因为不利于程序的维护
package net.ittimeline.java.core.foundational.operator.autodecrement;
/**
* 自减运算符案例:根据指定表达式计算i、j、k的值
*
* @author tony [email protected]
* @version 2023/7/21 13:50
* @since Java17
*/
public class AutoIncrementOperatorExample {
public static void main(String[] args) {
int i = 5;
int j = i-- + --i * i--;
/*
1. 先执行自减运算,计算i的值:自增自减运算符优先级高于算术运算符
i--等于5 i等于4
--i等于3 i等于3
i--等于3 i等于2
i-- + --i * i-- =5+3 * 3
2.计算i-- + --i * i--表达式的值:算术运算符先乘除,后加减
5+3 * 3=14
3.统计计算结果
i等于2
j等于14
*/
System.out.println("i = " + i);
System.out.println("j = " + j);
}
}
程序运行结果
Java语言中的等号(=)表示赋值,用于将等号(=)右边的值赋值给左边的变量,值可以是字面量、变量或者是表达式。
变量的首次赋值也被称为变量的初始化,而当变量多次被赋值后,新值会覆盖旧值。
int number = 10;
//第二次赋值时新值会覆盖旧值
number = 20;
当赋值号(=)两边数据类型不一致时,可以使用自动类型转换或者是强制类型转换进行处理。
double doubleValue = 5;
long longValue = 10;
int intValue = (int) 180.05;
byte byteValue = (byte) intValue;
Java支持连续赋值
int left;
int right;
//int left;和int right;等价于 int left,right;
left = right = 10;
赋值表达式本身也是有值,其值就是给变量赋的值。
int value = 10;
System.out.println("赋值表达式value=100的结果是 " + (value = 100));
赋值运算符还可以结合算术运算符使用,组成扩展赋值运算符
扩展赋值运算符 | 说明 |
---|---|
+= | 将符号左边的值和右边的值进行相加操作,最后将结果赋值给左边的变量 |
-= | 将符号左边的值和右边的值进行相减操作,最后将结果赋值给左边的变量 |
*= | 将符号左边的值和右边的值进行相乘操作,最后将结果赋值给左边的变量 |
/= | 将符号左边的值和右边的值进行相除操作,最后将结果赋值给左边的变量 |
%= | 将符号左边的值和右边的值进行取余操作,最后将结果赋值给左边的变量 |
AssignmentOperator.java演示赋值运算符基本使用
package net.ittimeline.java.core.foundational.operator.assignment;
/**
* 赋值运算符使用
*
* @author tony [email protected]
* @version 2023/7/21 14:26
* @since Java17
*/
public class AssignmentOperator {
public static void main(String[] args) {
//赋值运算符使用方式1:
int number = 10;
System.out.println("number = " + number);
//第二次赋值时新值会覆盖旧值
number = 20;
System.out.println("number = " + number);
//当=两侧数据类型不一致,可以使用自动类型转换或者使用强制类型转换原则进行处理
double doubleValue = 5;
long longValue = 10;
int intValue = (int) 180.05;
byte byteValue = (byte) intValue;
//支持连续赋值
//赋值运算符使用方式2:连续赋值
{
//非连续赋值
int left = 10;
int right = 10;
System.out.printf("非连续赋值 left=%d right=%d\n", left, right);
}
//连续赋值
int left;
int right;
//36行和37行 等价于 int left,right;
left = right = 10;
System.out.printf("连续赋值 left=%d right=%d\n", left, right);
//赋值运算符使用方式3:
int x = 10, y = 20, z = 30;
System.out.println("x = " + x);
System.out.println("y = " + y);
System.out.println("z = " + z);
//赋值表达式本身也是有值,其值就是给变量赋的值。
int value = 10;
System.out.println("赋值表达式value=100的结果是 " + (value = 100));
}
}
程序运行结果
ExtendsAssignmentOperator.java展示扩展运算符的使用
package net.ittimeline.java.core.foundational.operator.assignment;
/**
* 扩展赋值运算符使用
*
* @author tony [email protected]
* @version 2023/7/21 15:19
* @since Java17
*/
public class ExtendsAssignmentOperator {
public static void main(String[] args) {
int left = 20;
int right = 10;
System.out.println("left = " + left);
System.out.println("right = " + right);
//left += right 等价于left = left + right
// left等于10+20=30
left += right;
System.out.println("left += right = " + left);
//left -= right等价于left =left - right
// left 等于 30 - 10 = 20
left -= right;
System.out.println("left -= right = " + left);
// left *= right等价于left=left*right
// left=20 * 10 = 200
left *= right;
System.out.println("left *= right = " + left);
//left /= right等价于left = left / right
// left=200 / 10 = 20
left /= right;
System.out.println("left /= right = " + left);
//left %= right等价于left = left % right
// left = 20 / 10 = 0
left %= right;
System.out.println("left %= right = " + left);
left = 3;
// left *= right + 3等价于left = left * (right +3) =
// left等于3 * 13 =39
left *= right + 3;
System.out.println("left = " + left);
// 扩展赋值运算隐含强制类型转换
short shortVar = 20;
//shortVar+=10 等价于 shortVar =(short) (shortVar+10)
shortVar += 10;
// shortVar等于30
System.out.println("shortVar = " + shortVar);
//扩展赋值运算会自动进行强制类型转换
byte value = 10;
//如果不强制类型转换 会出现编译错误 不兼容的类型: 从int转换到byte可能会有损失
// byte result =value+2;
byte result = (byte) (value + 2);
System.out.println("result = " + result);
//另外一种方式 底层会做强制类型转换
// value += 2等价于 value = (byte) (value + 2)
//value += 2的类型还是byte
value += 2;
System.out.println("value = " + value);
//需要注意是否会产生溢出
byte temp = 126;
temp += 2;
// temp = -128 因为结果超过byte的表示范围
System.out.println("temp = " + temp);
//自增运算符也会进行自动类型转换
byte byteVal = 1;
//等价于 byteVal= (int)(byteVal+1);
byteVal++;
}
}
程序运行结果
赋值运算符的运算顺序是从右往左
赋值运算符的左边只能是变量,右边可以是变量、表达式、常量值
AssignmentOperatorWarning.java展示赋值运算符使用事项
package net.ittimeline.java.core.foundational.operator.assignment;
/**
* 赋值运算符使用注意事项
*
* @author tony [email protected]
* @version 2023/7/21 15:39
* @since Java17
*/
public class AssignmentOperatorWarning {
public static void main(String[] args) {
int number = 10;
System.out.println("赋值的时候右边是字面量 number = " + number);
// 赋值的时候左边必须是变量 否则编译错误
// 10=10;
// 10=number;
//赋值的时候右边必须是字面值、变量、表达式
int value = 20;
number = value;
System.out.println("赋值的时候右边是变量 number = " + number);
number = value / 2;
System.out.println("赋值的时候右边是算术表达式 number = " + number);
//赋值运算符的结合性是从右往左,其他的运算符都是从左往右
int left, middle, right;
left = middle = right = 100;
System.out.println("left = " + left);
System.out.println("middle = " + middle);
System.out.println("right = " + right);
}
}
程序运行结果
AssignmentOperatorExample1.java演示两种方式实现变量值加2
package net.ittimeline.java.core.foundational.operator.assignment;
/**
* 赋值运算符案例1:实现变量值增加2
*
* @author tony [email protected]
* @version 2023/7/21 15:42
* @since Java17
*/
public class AssignmentOperatorExample1 {
public static void main(String[] args) {
//方式1:推荐
int type1 = 1;
type1 += 2;
System.out.println("type1 = " + type1);
//方式2:
int type2 = 1;
type2 = type2 + 2;
System.out.println("type2 = " + type2);
}
}
程序运行结果
AssignmentOperatorExample2.java演示四种方式实现变量值加1
package net.ittimeline.java.core.foundational.operator.assignment;
/**
* 赋值运算符案例2:实现变量值加1
*
* @author tony [email protected]
* @version 2023/7/21 15:45
* @since Java17
*/
public class AssignmentOperatorExample2 {
public static void main(String[] args) {
//方式1:
int type1 = 1;
type1 += 1;
System.out.println("type1 = " + type1);
//方式2:
int type2 = 1;
type2 = type2 + 1;
System.out.println("type2 = " + type2);
//方式3:推荐
int type3 = 1;
type3++;
System.out.println("type3 = " + type3);
//方式4:
int type4 = 1;
++type4;
System.out.println("type4 = " + type4);
}
}
程序运行结果
关系运算符又称为比较运算符,主要用于数据的比较
Java语言提供了如下六种关系运算符
符号 | 案例 | 说明 |
---|---|---|
== | a==b | 判断a和b的值是否相等,成立为true,不成立为false |
!= | a!=b | 判断a和b的值是否不相等,成立为true,不成立为false |
> | a>b | 判断a是否大于b,成立为true,不成立为false |
>= | a>=b | 判断a是否大于等于b,成立为true,不成立为false |
< | a | 判断a是否小于b,成立为true,不成立为false |
<= | a<=b | 判断a是否小于或者等于b,成立为true,不成立为false |
>、<、 >=、 <= 只适用于基本数据类型(除 boolean 类型之外)
==和!= 适用于基本数据类型和引用数据类型
RelationOperatorIntegerLiteral.java展示 关系运算符比较整数字面量
package net.ittimeline.java.core.foundational.operator.relation;
/**
* 关系运算符比较整数字面量
*
* @author tony [email protected]
* @version 2023/7/21 15:59
* @since Java17
*/
public class RelationOperatorIntegerLiteral {
public static void main(String[] args) {
//使用整数字面量结合关系运算符实现数据的比较
System.out.println("5 > 3 = " + (5 > 3));
System.out.println("5 < 3 = " + (5 < 3));
//true
System.out.println("5 >= 3 = " + (5 >= 3));
//false
System.out.println("5 <= 3 = " + (5 <= 3));
//false
System.out.println("5 == 3 = " + (5 == 3));
//true
System.out.println("5 != 3 = " + (5 != 3));
//关系运算符的结果是boolean类型
boolean result = 5 > 3;
System.out.println("result = " + result);
}
}
程序运行结果
RelationOperatorCharacterLiteral.java展示关系运算符比较字符字面量
当字符参与比较时,比较的是字符所采用字符集的编号
package net.ittimeline.java.core.foundational.operator.relation;
/**
* 关系运算符比较字符字面量
*
* @author tony [email protected]
* @version 2023/7/21 16:01
* @since Java17
*/
public class RelationOperatorCharacterLiteral {
public static void main(String[] args) {
//a的编号是97 A的编号是65
System.out.println("'a' > 'A' = " + ('a' > 'A'));
System.out.println("'a' < 'A' = " + ('a' < 'A'));
System.out.println("'a' >= 'A' = " + ('a' >= 'A'));
System.out.println("'a' <= 'A' = " + ('a' <= 'A'));
System.out.println("'a' == 'A' = " + ('a' == 'A'));
System.out.println("'a' != 'A' = " + ('a' != 'A'));
}
}
程序运行结果
RelationOperatorIntegerVariable.java展示关系运算符比较整数变量
package net.ittimeline.java.core.foundational.operator.relation;
/**
* 关系运算符比较整数变量
*
* @author tony [email protected]
* @version 2023/7/21 16:03
* @since Java17
*/
public class RelationOperatorIntegerVariable {
public static void main(String[] args) {
int left = 10;
int right = 10;
System.out.println("left = " + left);
System.out.println("right = " + right);
//false
//第一个%d会被left的值替换
//第二个%d会被right的值替换
//%b会被left>right的值替换
System.out.printf("%d > %d 的结果是%b \n", left, right, (left > right));
//true
System.out.printf("%d >= %d 的结果是%b \n", left, right, (left >= right));
//false
System.out.printf("%d < %d 的结果是%b \n", left, right, (left < right));
//true
System.out.printf("%d <= %d 的结果是%b \n", left, right, (left <= right));
//true
System.out.printf("%d == %d 的结果是%b \n", left, right, (left == right));
//false
System.out.printf("%d != %d 的结果是%b \n", left, right, (left != right));
}
}
程序运行结果
关系运算符的运算结果是布尔类型的true或者false
是否相等(==)表示相等性,基本数据类型判断都是数值是否相等,引用数据类型判断的是对象的引用地址是否相等
是否不相等(!=) 表示不相等 ,基本数据类型判断都是数值是否不相等,引用数据类型判断的是对象的引用地址是否不相等
Java语言中的 == 表示是否相等,=表示赋值,千万不要把==误写成=
RelationOperatorWarning.java演示关系运算符使用注意事项1和4
package net.ittimeline.java.core.foundational.operator.relation;
/**
* 关系运算符使用注意事项
*
* @author tony [email protected]
* @version 2023/7/21 16:12
* @since Java17
*/
public class RelationOperatorWarning {
public static void main(String[] args) {
int left = 10;
int right = 20;
//1. 关系运算符的运算结果是布尔类型的true或者false
boolean result = left > right;
System.out.printf("%d > %d 的结果是%b\n", left, right, result);
result = left > right;
System.out.printf("%d >= %d 的结果是%b\n", left, right, result);
result = left < right;
System.out.printf("%d < %d 的结果是%b\n", left, right, result);
result = left <= right;
System.out.printf("%d <= %d 的结果是%b\n", left, right, result);
//4.Java语言中的 == 表示是否相等,=表示赋值,千万不要把==误写成=区分==和=
result = left == right;
System.out.printf("%d == %d 的结果是%b\n", left, right, result);
//left = right是赋值表达式,结果就是right
System.out.println("left=right = " + (left = right));
//布尔类型作为操作数
boolean boolVar1 = true;
boolean boolVar2 = false;
System.out.println("boolVar1==boolVar2 :" + (boolVar1 == boolVar2));
//不要把==写成=
System.out.println("boolVar2=true : " + (boolVar2 = true));
}
}
程序运行结果
符号 | 说明 | 运算规则 |
---|---|---|
& | 逻辑与 | 运算符左右两边的操作数都必须是true,运算结果返回true,否则返回false |
&& | 短路与 | 运算符左右两边的操作数都必须是true,运算结果返回true,否则返回false;增加了短路特性:左边为false,则右边就不执行 |
| | 逻辑或 | 运算符左右两边的操作数只要有一个为true,运算结果返回true,否则返回false |
|| | 短路或 | 运算符左右两边的操作数只要有一个为true,运算结果返回true,否则返回false;增加了短路特性:左边为true,则右边就不执行 |
! | 逻辑非 | 取反,操作数为true时逻辑非的运算结果为false,逻辑非只有一个操作数 |
^ | 逻辑异或 | 当两个操作数不同的时候返回true,当两个操作数相同的时候返回false |
日常开发中经常使用的逻辑运算符是短路与、短路或和逻辑非
逻辑运算符的操作数都是布尔类型的数据,例如布尔类型的字面值、变量、表达式(例如关系表达式) 逻辑运算符的运算结果也是布尔类型的true或者false
短路与、 短路或的短路特性:当已经明确逻辑运算的最终结果,就不会再计算剩余的表达式,如果剩余的表达式计算机特别耗时,这样可以提升程序性能
&&左边的表达式结果为false不会再执行&&右边的表达式,因为整个表达式的最终结果已经是false
||左边的表达式计算结果为true不会再执行||右边的表达式,因为整个表达式的最终结果已经是true
LogicOperator.java演示逻辑运算符的使用
package net.ittimeline.java.core.foundational.operator.logic;
/**
* 逻辑运算符的使用-操作布尔字面量
*
* @author tony [email protected]
* @version 2023/7/21 16:26
* @since Java17
*/
public class LogicOperator {
public static void main(String[] args) {
// 1.逻辑与(&) :运算符左右两边的操作数都必须是true,运算结果返回true,否则返回false
System.out.println("1.逻辑与的使用");
System.out.println("true & true = " + (true & true));
System.out.println("true & false = " + (true & false));
System.out.println("false & true = " + (false & true));
System.out.println("false & false = " + (false & false));
// 2.短路与(&&):运算符左右两边的操作数都必须是true,运算结果返回true,否则返回false,增加了短路特性
System.out.println("2.短路与的使用");
//按住滚轮选择多个列
System.out.println("true && true = " + (true && true));
System.out.println("true && false = " + (true && false));
System.out.println("false && true = " + (false && true));
System.out.println("false && false = " + (false && false));
// 3.逻辑或(|):运算符左右两边的操作数只要有一个为true,运算结果返回true,否则返回false
System.out.println("3.逻辑或的使用");
System.out.println("false | false = " + (false | false));
System.out.println("true | false = " + (true | false));
System.out.println("false | true = " + (false | true));
System.out.println("true | true = " + (true | true));
// 4.短路或(||):运算符左右两边的操作数只要有一个为true,运算结果返回true,否则返回false,增加了短路特性
System.out.println("4.短路或的使用");
System.out.println("false || false = " + (false || false));
System.out.println("true || false = " + (true || false));
System.out.println("false || true = " + (false || true));
System.out.println("true || true = " + (true || true));
// 5. 逻辑非(!):取反,操作数为true时逻辑非的运算结果为false,逻辑非只有一个操作数
System.out.println("5.逻辑非的使用");
System.out.println("!true = " + !true);
//实际开发中要么不使用逻辑非(!),要么只会写一个!
System.out.println("!!true = " + !!true);
System.out.println("!false = " + !false);
System.out.println("!!false = " + !!false);
// (60>30) = true
System.out.println("( 60 > 30) = " + (60 > 30));
// !(60>30) = false
System.out.println("!( 60 > 30) = " + !(60 > 30));
// 6.逻辑异或(^):当两个操作数不同的时候返回true,当两个操作数相同的时候返回false
System.out.println("6.逻辑异或的使用");
System.out.println("false ^ true = " + (false ^ true));
System.out.println("true ^ false = " + (true ^ false));
System.out.println("true ^ true = " + (true ^ true));
System.out.println("false ^ false = " + (false ^ false));
//true ^ true = false
boolean result = (10 > 1) ^ (3 < 5);
System.out.println("result = " + result);
// true ^ false = true
result = (10 > 1) ^ (3 > 5);
System.out.println("result = " + result);
}
}
程序运行结果
逻辑与和短路与相同点:两个运算符表达的都是且的关系,只有当符号左右两边的结果都为true,结果才为true
逻辑与和短路与不同点(执行流程):如果运算符左边是true,则逻辑与、短路与都会执行运算符右边的操作。如果运算符左边是false,则逻辑与会继续执行运算符右边的操作,但是短路与不会执行运算符右边的操作,即短路。
LogicAndShortCircuitAndDifferenceExample.java演示逻辑与和短路与的区别
package net.ittimeline.java.core.foundational.operator.logic;
/**
* 逻辑与和短路与的区别
*
* @author tony [email protected]
* @version 2023/7/21 16:41
* @since Java17
*/
public class LogicAndShortCircuitAndDifferenceExample {
public static void main(String[] args) {
/*
逻辑与和短路与相同点:两个运算符表达的都是且的关系,只有当符号左右两边的结果都为true,结果才为true
逻辑与和短路与不同点(执行流程):如果运算符左边是true,则逻辑与、短路与都会执行运算符右边的操作。如果运算符左边是false,则逻辑与会继续执行运算符右边的操作,但是短路与不会执行运算符右边的操作,即短路。
*/
//逻辑与的使用
{
System.out.println("1.逻辑与的使用");
int x = 1;
int y = 1;
if (x++ == 2 & ++y == 2) {
x = 7;
}
//x等于2
System.out.println("x = " + x);
// y等于2
System.out.println("y = " + y);
}
//短路与的使用
{
System.out.println("2.短路与的使用");
int x = 1, y = 1;
if (x++ == 2 && ++y == 2) {
x = 7;
}
//x等于2
System.out.println("x = " + x);
//y等于1
System.out.println("y = " + y);
}
}
}
程序运行结果
逻辑或(|)与短路或(||)的相同点:两个运算符表达的都是或的关系,只要运算符两边有一边的结果是true,那么运算结果就是true
逻辑或(|)和短路或(||)不同点(执行流程):如果运算符左边是false,则逻辑或(|)和短路或(||)都会执行右边的操作 ,如果运算符左边是true,整个运算结果已经是true,则逻辑或(|)会继续执行右边的操作,但是短路或(||)不会继续执行右边的操作,即短路。
LogicOrShortCircuitOrDifferenceExample.java演示逻辑或与短路或的区别
package net.ittimeline.java.core.foundational.operator.logic;
/**
* 逻辑或与短路或的区别
*
* @author tony [email protected]
* @version 2023/7/21 16:58
* @since Java17
*/
public class LogicOrShortCircuitOrDifferenceExample {
public static void main(String[] args) {
/*
逻辑或(|)与短路或(||)的相同点:两个运算符表达的都是或的关系,只要运算符两边有一边的结果是true,那么运算结果就是true
逻辑或(|)和短路或(||)不同点(执行流程):如果运算符左边是false,则逻辑或(|)和短路或(||)都会执行右边的操作
如果运算符左边是true,整个运算结果已经是true,则逻辑或(|)会继续执行右边的操作,但是短路或(||)不会继续执行右边的操作,即短路。
*/
//逻辑或的使用
{
System.out.println("1.逻辑或的使用");
int x = 1, y = 1;
if (x++ == 1 | ++y == 1) {
x = 7;
}
// x等于7
System.out.println("x = " + x);
//y等于2
System.out.println("y = " + y);
}
//短路或的使用
{
System.out.println("2.短路或的使用");
int x = 1, y = 1;
if (x++ == 1 || ++y == 1) {
x = 7;
}
// x等于7
System.out.println("x = " + x);
//y等于1
System.out.println("y = " + y);
}
}
}
程序运行结果
package net.ittimeline.java.core.foundational.operator.logic;
/**
* 逻辑运算符案例1:判断程序输出结果
*
* @author tony [email protected]
* @version 2023/7/21 17:07
* @since Java17
*/
public class LogicOperatorExample1 {
public static void main(String[] args) {
int left, right;
left = right = 20;
/*
++left等于21;
21%3等于0
left++等于21
left等于22
booleanVar1等于true
*/
boolean booleanVar1 = (++left % 3 == 0) && (left++ % 7 == 0);
System.out.println("left = " + left);
System.out.println("booleanVar1 = " + booleanVar1);
/*
right++等于20 right等于21
right++%3==0 等于false
right等于21
booleanVar2等于false
*/
boolean booleanVar2 = (right++ % 3 == 0) && (++right % 7 == 0);
System.out.println("right = " + right);
System.out.println("booleanVar2 = " + booleanVar2);
}
}
程序运行结果
package net.ittimeline.java.core.foundational.operator.logic;
/**
* 逻辑运算符案例2:判断程序输出结果
* @author tony [email protected]
* @version 2023/7/21 17:10
* @since Java17
*/
public class LogicOperatorExample2 {
public static void main(String[] args) {
boolean x = true;
boolean y = false;
short s = 42;
//第一个if执行完s等于44
if ((s++ == 42) && (y = true)) {
s++;
}
//第二个if执行完s等于46
if ((x = false) || (++s == 45)) {
s++;
}
//最后结果是s等于46
System.out.println("s = " + s);
}
}
程序运行结果
三目运算符又叫做三元运算符或者是条件运算符,其作用就是用来进行条件判断,根据不同的判断结果获得不同的内容。
三目运算符的语法格式
条件表达式?表达式1:表达式2
三目运算符的执行流程
执行条件表达式,条件表达式的结果是boolean类型
如果条件表达式成立,就执行表达式1,表达式1的值就是三目运算的结果
如果条件表达式不成立,就执行表达式2,表达式2的值就是三目运算的结果
TernaryOperator演示三元运算符的使用,实现求两个整数的最大值,两个整数是用户从键盘输入
package net.ittimeline.java.core.foundational.operator.ternary;
import java.util.Scanner;
/**
* 三目运算符的使用
*
* @author tony [email protected]
* @version 2023/7/21 17:17
* @since Java17
*/
public class TernaryOperator {
public static void main(String[] args) {
//需求:求两个数的最大值
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个整数");
int left = scanner.nextInt();
System.out.println("请输入第二个整数");
int right = scanner.nextInt();
//三元运算符的结果必须必须要被使用,例如赋值给max存储
//left > right ? left : right;
//三元运算符的语法格式: 关系表达式?表达式1:表达式2
int max = left > right ? left : right;
System.out.printf("你输入的第一个整数是%d 第二个整数是%d 两个整数中的最大值是%d\n", left, right, max);
scanner.close();
}
}
程序运行结果
三元运算结果必须要被使用,例如打印输出或者赋值,否则会编译错误
如果三元表达式运算后的结果赋值给新的变量,要求表达式 1 和表达式 2 为同种或兼容的类型
开发中使用三元运算符的地方都可以改成if/else,反之不一定。建议在二者都能使用的情况下,推荐使用三元运算符,因为执行效率略高
TernaryOperatorWarning.java演示三元运算符的注意事项
package net.ittimeline.java.core.foundational.operator.ternary;
/**
* 三元运算符使用注意事项
*
* @author tony [email protected]
* @version 2023/7/21 18:39
* @since Java17
*/
public class TernaryOperatorWarning {
public static void main(String[] args) {
//1. 三元运算结果必须要被使用,例如打印输出或者赋值,否则会编译错误
int age = 19;
//编译错误
//(age>18)?"你成年了":"你未成年";
//表达式1和表达式2都是String类型
String result = (age > 18) ? "你成年了" : "你未成年";
System.out.println("result = " + result);
// 2. 如果三元表达式运算后的结果赋值给新的变量,要求表达式 1 和表达式 2 为同种或兼容的类型
/*
表达式1和表达式2都是数值类型
三元运算的结果是取两个表达式中取值范围最大的那个数据类型
因此三元运算的结果类型是double
*/
double doubleResult = (2 > 1) ? 1 : 2.0;
System.out.println("doubleResult = " + doubleResult);
//3.开发中使用三元运算符的地方都可以改成if/else,反之不一定。建议在二者都能使用的情况下,推荐使用三元运算符,因为执行效率略高
//if/else判断是否成年,成年才能去网吧上网
if (age >= 18) {
System.out.println("你成年了,可以去网吧上网了");
} else {
System.out.println("未成年人不能去网吧上网");
}
//三元运算判断是否成年,成年才能去网吧上网
result = age >= 18 ? "你成年了,可以去网吧上网了" : "未成年人不能去网吧上网";
System.out.println(result);
}
}
程序运行结果
需求:用户从键盘依次输入三个整数,求三个三个整数中的最大值
分析:
① 先求出两个整数中的最大值
② 再求出三个整数中的最大值
TernaryOperatorExample1GetThreeIntegerMax.java演示求三个整数的最大值具体实现过程
package net.ittimeline.java.core.foundational.operator.ternary;
import java.util.Scanner;
/**
* 三目运算符案例1:求三个整数的最大值
*
* @author tony [email protected]
* @version 2023/7/21 18:07
* @since Java17
*/
public class TernaryOperatorExample1GetThreeIntegerMax {
public static void main(String[] args) {
//需求:求三个数的最大值
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个整数");
int first = scanner.nextInt();
System.out.println("请输入第二个整数");
int second = scanner.nextInt();
System.out.println("请输入第三个整数");
int third = scanner.nextInt();
//先求出两个整数的最大值
int secondMax=first>second?first:second;
//再求出三个整数的最大值
int max =secondMax>third?secondMax:third;
System.out.printf("你输入的第一个整数是%d 第二个整数是%d 第三个整数是%d 三个整数中的最大值是%d\n", first,second,third, max);
scanner.close();
}
}
程序运行结果
需求:用户从键盘依次输入三个整数,求三个整数中的最小值
分析:
① 先求出两个整数中的最小值
② 再求出三个整数中的最小值
package net.ittimeline.java.core.foundational.operator.ternary;
import java.util.Scanner;
/**
* 三目运算符案例2:求三个整数的最小值
*
* @author tony [email protected]
* @version 2023/7/21 18:29
* @since Java17
*/
public class TernaryOperatorExample1GetThreeIntegerMin {
public static void main(String[] args) {
//需求:求三个数的最小值
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一个整数");
int first = scanner.nextInt();
System.out.println("请输入第二个整数");
int second = scanner.nextInt();
System.out.println("请输入第三个整数");
int third = scanner.nextInt();
//先求出两个整数的最小值
int secondMin = first < second ? first : second;
//再求出三个整数的最小值
int min = secondMin < third ? secondMin : third;
System.out.printf("你输入的第一个整数是%d 第二个整数是%d 第三个整数是%d 三个整数中的最小值是%d\n", first, second, third, min);
scanner.close();
}
}
程序运行结果
需求:动物园里有两只老虎,体重分别从键盘输入,请用程序实现判断两只老虎的体重是否相同,如果相同打印输出相同,否则打印输出不同。
TernaryOperatorJudgeTigerWeightExample1.java演示判断老虎体重是否相等的具体实现过程
package net.ittimeline.java.core.foundational.operator.ternary;
import java.util.Scanner;
/**
* 三目运算符案例2:判断老虎体重是否相等
*
* @author tony [email protected]
* @version 2023/7/21 18:01
* @since Java17
*/
public class TernaryOperatorExample2JudgeTigerWeight {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入第一只老虎的体重(单位:克)");
int firstTigerWeight = scanner.nextInt();
System.out.println("请输入第二只老虎的体重(单位:克)");
int secondTigerWeight = scanner.nextInt();
String result = firstTigerWeight == secondTigerWeight ? "相同" : "不相同";
System.out.println("两只老虎的体重" + result);
scanner.close();
}
}
程序运行结果
需求:用户从键盘输入一个整数后,判断是整数还是负数或者是0
TernaryOperatorExample3JudgePositiveNumberNegativeNumberZero.java演示判断用户输入的是正数还是负数或者0
package net.ittimeline.java.core.foundational.operator.ternary;
import java.util.Scanner;
/**
* 判断用户输入的是正数还是负数或者0
*
* @author tony [email protected]
* @version 2023/7/21 18:15
* @since Java17
*/
public class TernaryOperatorExample3JudgePositiveNumberNegativeNumberZero {
public static void main(String[] args) {
//创建Scanner对象
//System.in 标准输入 也就是键盘输入
//Scanner对象可以扫描用户从键盘输入的数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数");
int number = scanner.nextInt();
String result = number > 0 ? "正数" : (number < 0 ? "负数" : "0");
System.out.println("用户输入的是" + result);
scanner.close();
}
}
程序运行结果
Q:为什么要学习位运算
A:由于其运算效率更高,JDK源码(例如ArrayList)中大量使用位运算,想要看懂JDK源码必须懂位运算,但是Java项目开发中位运算使用并不多。
Q:学习位运算需要提前储备什么
A:由于位运算底层运算是基于二进制,因此需要掌握进制,包括二进制、十进制以及它们的相互转换,除此以外还需要掌握原码、反码、补码及其它们的相互转换
Java提供了7个位运算符
位运算符 | 说明 | 计算规则 |
---|---|---|
& | 按位与 | 按照二进制位进行与运算,同1为1,有0为0 |
| | 按位或 | 按照二进制位进行或运算,有1为1,同0为0 |
~ | 按位取反 | 按照二进制位取反,1为0,0为1 |
^ | 按位异或 | 按照二进制位进行异或运算,相同为0,不同为1 |
<< | 左移运算符 | 用于将数据的二进制位向左移动,右边填充0。左移n位在一定范围内就是乘以2的n次方 |
>> | 右移运算符 | 用于将数据的二进制位向右移动,左边填充符号位,符号位是0填充0,符号位是1就填充1。 右移n位在一定范围内就是除以2的n次方 |
>>> | 无符号右移运算符 | 用于将数据的二进制位向右移动,左边填充0 |
二进制位包括符号位和数据位
按位运算符的按位与、按位或、按位异或和逻辑运算符的逻辑与、逻辑或、逻辑异或使用相同的符
Q:如何确定符号是位运算符还是逻辑运算符?
A:看运算符的操作数即可,如果操作数是操作的整数那么就是位运算符,如果操作数操作的是boolean类型的数据就是逻辑运算符。
BitAndOperatorExample1PositiveNumber.java演示按位与操作正数,而且在程序中使用多行注释说明按位与的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位与案例1:操作数是正数
*
* @author tony [email protected]
* @version 2023/7/21 19:31
* @since Java17
*/
public class BitAndOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求5和2的补码
计算机中的数据是使用补码进行计算的
由于5和2都是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
2的补码:0000 0000 0000 0000 0000 0000 0000 0010
2. 按照按位与的计算规则计算:按照二进制位进行与运算,同1为1,有0为0
0000 0000 0000 0000 0000 0000 0000 0101
&
0000 0000 0000 0000 0000 0000 0000 0010
=
0000 0000 0000 0000 0000 0000 0000 0000
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0000左边的最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0000
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0000转换成十进制的结果是0
因此5 & 2的结果是0
*/
System.out.println("5 & 2 = " + (5 & 2));
/*
1.先求5和3的补码
计算机中的数据是使用补码进行计算的
由于5和3都是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
3的补码:0000 0000 0000 0000 0000 0000 0000 0011
2. 按位与的计算规则:按照二进制位进行与运算,同1为1,有0为0
0000 0000 0000 0000 0000 0000 0000 0101
&
0000 0000 0000 0000 0000 0000 0000 0011
=
0000 0000 0000 0000 0000 0000 0000 0001
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0001左边的最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0001
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0001转换成十进制的结果是1
因此5 & 3的结果是1
*/
System.out.println("5 & 3 = " + (5 & 3));
}
}
程序运行结果
BitAndOperatorExample2NegativeNumber.java演示按位与操作负数,而且在程序中使用多行注释说明按位与的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位与案例2:操作数是负数
*
* @author tony [email protected]
* @version 2023/7/21 19:40
* @since Java17
*/
public class BitAndOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-5和-10的补码
计算机中的数据是使用补码进行计算的
由于-5和-10都是负数,最高位(符号位)是1
①计算5和10的原码
5的原码: 0000 0000 0000 0000 0000 0000 0000 0101
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-5和-10的原码
-5的原码: 1000 0000 0000 0000 0000 0000 0000 0101
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-5和-10的反码
原码求反码:原码最高位不变,其他位取反
-5的反码: 1111 1111 1111 1111 1111 1111 1111 1010
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-5和-10的补码
反码求补码:补码=反码+1
-5的补码: 1111 1111 1111 1111 1111 1111 1111 1011
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照按位与的计算规则计算:按照二进制位进行与运算,同1为1,有0为0
1111 1111 1111 1111 1111 1111 1111 1011
&
1111 1111 1111 1111 1111 1111 1111 0110
=
1111 1111 1111 1111 1111 1111 1111 0010
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1111 0010-1=1111 1111 1111 1111 1111 1111 1111 0001
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0000 1110
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0000 1110
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0000 1110转换成十进制的结果是-14
因此-5 & -10的结果是-14
*/
System.out.println("-5 & -10 = " + (-5 & -10));
}
}
BitOrOperatorExample1PositiveNumber.java展示按位或操作正数,而且在程序中使用多行注释说明按位或的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位或案例1:操作数是正数
*
* @author tony [email protected]
* @version 2023/7/21 19:52
* @since Java17
*/
public class BitOrOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求5和2的补码
计算机中的数据是使用补码进行计算的
由于5和2都是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
2的补码:0000 0000 0000 0000 0000 0000 0000 0010
2. 按照按位或的计算规则计算:按照二进制位进行或运算,有1为1,同0为0
0000 0000 0000 0000 0000 0000 0000 0101
|
0000 0000 0000 0000 0000 0000 0000 0010
=
0000 0000 0000 0000 0000 0000 0000 0111
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0111左边的最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0111
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0111转换成十进制的结果是7
因此5 | 2的结果是7
*/
System.out.println("5 | 2 = " + (5 | 2));
/*
1.先求5和3的补码
计算机中的数据是使用补码进行计算的
由于5和3都是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
3的补码:0000 0000 0000 0000 0000 0000 0000 0011
2. 按照按位或的计算规则计算:按照二进制位进行或运算,有1为1,同0为0
0000 0000 0000 0000 0000 0000 0000 0101
|
0000 0000 0000 0000 0000 0000 0000 0011
=
0000 0000 0000 0000 0000 0000 0000 0111
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0111左边的最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0111
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0111转换成十进制的结果是1
因此5 | 3的结果是1
*/
System.out.println("5 | 3 = " + (5 | 3));
}
}
程序运行结果
BitOrOperatorExample2NegativeNumber.java演示按位或操作负数,而且在程序中使用多行注释说明按位或的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位或案例2:操作数是负数
*
* @author tony [email protected]
* @version 2023/7/21 19:56
* @since Java17
*/
public class BitOrOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-5和-10的补码
计算机中的数据是使用补码进行计算的
由于-5和-10都是负数,最高位(符号位)是1
①计算5和10的原码
5的原码: 0000 0000 0000 0000 0000 0000 0000 0101
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-5和-10的原码
-5的原码: 1000 0000 0000 0000 0000 0000 0000 0101
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-5和-10的反码
原码求反码:原码最高位不变,其他位取反
-5的反码: 1111 1111 1111 1111 1111 1111 1111 1010
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-5和-10的补码
反码求补码:补码=反码+1
-5的补码: 1111 1111 1111 1111 1111 1111 1111 1011
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照按位或的计算规则计算:按照二进制位进行或运算,有1为1,同0为0
1111 1111 1111 1111 1111 1111 1111 1011
|
1111 1111 1111 1111 1111 1111 1111 0110
=
1111 1111 1111 1111 1111 1111 1111 1111
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1111 1111-1=1111 1111 1111 1111 1111 1111 1111 1110
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0000 0001
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0000 0001
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0000 0001转换成十进制的结果是-1
因此-5 | -10的结果是-1
*/
System.out.println("-5 | -10 = " + (-5 | -10));
}
}
程序运行结果
BitXorOperatorExample1PositiveNumber.java演示按位异或操作正数,而且在程序中使用多行注释说明按位异或的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位异或案例1:操作正数
*
* @author tony [email protected]
* @version 2023/7/21 20:02
* @since Java17
*/
public class BitXorOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求5和3的补码
计算机中的数据是使用补码进行计算的
由于5和3都是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
3的补码:0000 0000 0000 0000 0000 0000 0000 0011
2. 按照按位异或的计算规则计算:按照二进制位进行异或运算,相同为0,不同为1
0000 0000 0000 0000 0000 0000 0000 0101
^
0000 0000 0000 0000 0000 0000 0000 0011
=
0000 0000 0000 0000 0000 0000 0000 0110
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0110左边的最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0110
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0110转换成十进制的结果是6
因此5 ^ 3的结果是6
*/
System.out.println("5 ^ 3 = " + (5 ^ 3));
}
}
程序运行结果
BitXorOperatorExample2NegativeNumber.java演示按位异或操作负数,而且在程序中使用多行注释说明按位异或的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位异或案例2:操作负数
*
* @author tony [email protected]
* @version 2023/7/21 20:05
* @since Java17
*/
public class BitXorOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-5和-10的补码
计算机中的数据是使用补码进行计算的
由于-5和-10都是负数,最高位(符号位)是1
①计算5和10的原码
5的原码: 0000 0000 0000 0000 0000 0000 0000 0101
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-5和-10的原码
-5的原码: 1000 0000 0000 0000 0000 0000 0000 0101
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-5和-10的反码
原码求反码:原码最高位不变,其他位取反
-5的反码: 1111 1111 1111 1111 1111 1111 1111 1010
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-5和-10的补码
反码求补码:补码=反码+1
-5的补码: 1111 1111 1111 1111 1111 1111 1111 1011
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照按位异或的计算规则计算:按照二进制位进行异或运算,相同为0,不同为1
1111 1111 1111 1111 1111 1111 1111 1011
^
1111 1111 1111 1111 1111 1111 1111 0110
=
0000 0000 0000 0000 0000 0000 0000 1101
3.将补码换算成原码
0000 0000 0000 0000 0000 0000 0000 1101 最高位是0表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 1101
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 1101 转换成十进制的结果是13
因此-5 ^ -10的结果是13
*/
System.out.println("-5 ^ -10 = " + (-5 ^ -10));
}
}
程序运行结果
BitNotOperatorExample1PositiveNumber.java演示按位取反操作正数,而且在程序中使用多行注释说明按位取反的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位取反案例1:操作数是正数
*
* @author tony [email protected]
* @version 2023/7/21 20:25
* @since Java17
*/
public class BitNotOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求5的补码
计算机中的数据是使用补码进行计算的
由于5是正数,正数的原码、反码、补码都一样
5的补码:0000 0000 0000 0000 0000 0000 0000 0101
2. 按照按位取反的计算规则计算:按照二进制位取反,1为0,0为1
0000 0000 0000 0000 0000 0000 0000 0101
~
=
1111 1111 1111 1111 1111 1111 1111 1010
3.将补码换算成原码
由于1111 1111 1111 1111 1111 1111 1111 1010左边的最高位是1,表示负数
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1111 1010-1=1111 1111 1111 1111 1111 1111 1111 1001
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0000 0110
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0000 0110
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0000 0110转换成十进制的结果是-6
因此~5的结果是-6
*/
System.out.println("~5 = " + ~5);
}
}
程序运行结果
BitNotOperatorExample2NegativeNumber.java演示按位取反操作负数,而且在程序中使用多行注释说明按位取反的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 按位取反案例2:操作数是负数
*
* @author tony [email protected]
* @version 2023/7/21 20:30
* @since Java17
*/
public class BitNotOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-5的补码
计算机中的数据是使用补码进行计算的
由于-5是负数,最高位(符号位)是1
①计算5原码
5的原码: 0000 0000 0000 0000 0000 0000 0000 0101
②计算-5的原码
-5的原码: 1000 0000 0000 0000 0000 0000 0000 0101
③计算机-5的反码
原码求反码:原码最高位不变,其他位取反
-5的反码: 1111 1111 1111 1111 1111 1111 1111 1010
④计算-5的补码
反码求补码:补码=反码+1
-5的补码: 1111 1111 1111 1111 1111 1111 1111 1011
2.按照按位取反的计算规则计算:按照二进制位取反,1为0,0为1
1111 1111 1111 1111 1111 1111 1111 1011
~
=
0000 0000 0000 0000 0000 0000 0000 0100
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0100左边的最高位是0,表示正数
正数的原码、反码、补码都一样
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0100
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0100转换成十进制的结果是4
因此~-5的结果是4
*/
System.out.println("~-5 = " + ~-5);
}
}
程序运行结果
LeftMoveBitOperatorExample1PositiveNumber.java演示左移运算符操作正数,而且在程序中使用多行注释说明左移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 左移运算符案例1:操作正数
*
* @author tony [email protected]
* @version 2023/7/21 20:40
* @since Java17
*/
public class LeftMoveBitOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照左移的计算规则计算:用于将数据的二进制位向左移动,右边填充0。左移n位在一定范围内就是乘以2的n次方
0000 0000 0000 0000 0000 0000 0000 0110
<<1 二进制位左边删一个0,右边加一个0
=
0000 0000 0000 0000 0000 0000 0000 1100
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 1100 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 1100
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 1100转换成十进制的结果是12
因此6 << 2的结果是12
*/
System.out.println("6 << 1 = " + (6 << 1));
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照左移的计算规则计算:用于将数据的二进制位向左移动,右边填充0。左移n位在一定范围内就是乘以2的n次方
0000 0000 0000 0000 0000 0000 0000 0110
<<1 二进制位左边删两个0,右边加两个0
=
0000 0000 0000 0000 0000 0000 0001 1000
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0001 1000 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是00000 0000 0000 0000 0000 0000 0001 1000
4.将原码转换成十进制
00000 0000 0000 0000 0000 0000 0001 1000转换成十进制的结果是24
因此6 << 2的结果是24
*/
System.out.println("6 << 2 = " + (6 << 2));
}
}
程序运行结果
LeftMoveBitOperatorExample2NegativeNumber.java演示左移运算符操作负数,而且在程序中使用多行注释说明左移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 左移运算符案例2:操作负数
*
* @author tony [email protected]
* @version 2023/7/21 20:49
* @since Java17
*/
public class LeftMoveBitOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照左移的计算规则计算:用于将数据的二进制位向左移动,右边填充0。左移n位在一定范围内就是乘以2的n次方
1111 1111 1111 1111 1111 1111 1111 0110
<<1 二进制位左边删一个1,右边加一个0
=
1111 1111 1111 1111 1111 1111 1110 1100
最高位是1,表示它是一个负数
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1110 1100-1=1111 1111 1111 1111 1111 1111 1110 1011
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0001 0100
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0001 0100
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0001 0100 转换成十进制的结果是-20
因此-10 << 1的结果就是-20
*/
System.out.println("-10 << 1 = " + (-10 << 1));
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照左移的计算规则计算
用于将数据的二进制位向左移动,右边填充0。左移n位在一定范围内就是乘以2的n次方
1111 1111 1111 1111 1111 1111 1111 0110
<<2 二进制位左边删两个1,右边加两个0
=
1111 1111 1111 1111 1111 1111 1101 1000
最高位是1,表示它是一个负数
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1101 1000-1=1111 1111 1111 1111 1111 1111 1101 0111
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0010 1000
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0010 1000
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0010 1000 转换成十进制的结果是-40
因此-10 << 2的结果是-40
*/
System.out.println("-10 << 2 = " + (-10 << 2));
}
}
程序运行结果
RightMoveBitOperatorExample1PositiveNumber.java演示右移运算符操作正数,而且在程序中使用多行注释说明右移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 右移运算符案例1:操作正数
*
* @author tony [email protected]
* @version 2023/7/21 21:13
* @since Java17
*/
public class RightMoveBitOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充符号位,符号位是0填充0,符号位是1就填充0。 右移n位在一定范围内就是除以2的n次方
0000 0000 0000 0000 0000 0000 0000 0110
>>1 二进制位右边删一个0,左边加一个0
=
0000 0000 0000 0000 0000 0000 0000 0011
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0011 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0011
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0011转换成十进制的结果是3
因此6 >> 1的结果是3
*/
System.out.println("6 >> 1 = " + (6 >> 1));
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充符号位,符号位是0填充0,符号位是1就填充0。 右移n位在一定范围内就是除以2的n次方
0000 0000 0000 0000 0000 0000 0000 0110
>>2 二进制位左边加两个0,右边删10
=
0000 0000 0000 0000 0000 0000 0000 0001
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0001 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0001
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0001转换成十进制的结果是1
因此6 >> 2的结果是1
*/
System.out.println("6 >> 2 = " + (6 >> 2));
}
}
程序运行结果
RightMoveBitOperatorExample2NegativeNumber演示右移运算符操作负数,而且在程序中使用多行注释说明右移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 右移运算符案例2:操作负数
*
* @author tony [email protected]
* @version 2023/7/21 21:22
* @since Java17
*/
public class RightMoveBitOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照右移的计算规则计算: 用于将数据的二进制位向右移动,左边填充符号位,符号位是0填充0,符号位是1就填充1。 右移n位在一定范围内就是除以2的n次方
1111 1111 1111 1111 1111 1111 1111 0110
>>1 二进制位右边删一个0,左边加一个1
=
1111 1111 1111 1111 1111 1111 1111 1011
最高位是1,表示它是一个负数
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1111 1011-1=1111 1111 1111 1111 1111 1111 1111 1010
②反码转换成原码:反码最高位不变,其他位取反
1111 1111 1111 1111 1111 1111 1111 1010
1000 0000 0000 0000 0000 0000 0000 0101
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0000 0101
最高位是1,表示它是一个负数
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0000 0101 转换成十进制的结果是-5
因此-10 << 1的结果就是-5
*/
System.out.println("-10 >> 1 = " + (-10 >> 1));
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照左移的计算规则计算
用于将数据的二进制位向右移动,左边填充符号位,符号位是0填充0,符号位是1就填充1。 右移n位在一定范围内就是除以2的n次方
1111 1111 1111 1111 1111 1111 1111 0110
>> 2 二进制位左边加两个1,右边删10
=
1111 1111 1111 1111 1111 1111 1111 1101
最高位是1,表示它是一个负数
3.将补码换算成原码
①先转换成反码:反码=补码-1
1111 1111 1111 1111 1111 1111 1111 1101-1= 1111 1111 1111 1111 1111 1111 1111 1100
②反码转换成原码:反码最高位不变,其他位取反
1000 0000 0000 0000 0000 0000 0000 0011
补码转换成原码的结果是1000 0000 0000 0000 0000 0000 0000 0011
4.将原码转换成十进制
1000 0000 0000 0000 0000 0000 0000 0011 转换成十进制的结果是-3
因此-10 >> 2的结果是-3
*/
System.out.println("-10 >> 2 = " + (-10 >> 2));
}
}
程序运行结果
UnsignedRightMoveOperatorExample1PositiveNumber.java演示无符号右移操作正数,而且在程序中使用多行注释说明无符号右移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 无符号右移案例1:操作正数
*
* @author tony [email protected]
* @version 2023/7/21 21:40
* @since Java17
*/
public class UnsignedRightMoveOperatorExample1PositiveNumber {
public static void main(String[] args) {
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充0
0000 0000 0000 0000 0000 0000 0000 0110
>>> 1 二进制位左边加一个0,右边删一个0
=
0000 0000 0000 0000 0000 0000 0000 0011
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0011 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0011
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0011转换成十进制的结果是3
因此6 >>> 1的结果是3
*/
System.out.println("6 >>> 1 = " + (6 >>> 1));
/*
1.先求6的补码
计算机中的数据是使用补码进行计算的
由于6是正数,正数的原码、反码、补码都一样
6的补码:0000 0000 0000 0000 0000 0000 0000 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充0
0000 0000 0000 0000 0000 0000 0000 0110
>>2 二进制位左边加两个0,右边删10
=
0000 0000 0000 0000 0000 0000 0000 0001
3.将补码换算成原码
由于0000 0000 0000 0000 0000 0000 0000 0001 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0000 0000 0000 0000 0000 0000 0000 0001
4.将原码转换成十进制
0000 0000 0000 0000 0000 0000 0000 0001转换成十进制的结果是1
因此6 >>> 2的结果是1
*/
System.out.println("6 >>> 2 = " + (6 >>> 2));
}
}
程序运行结果
UnsignedRightMoveOperatorExample2NegativeNumber演示无符号右移操作负数,而且在程序中使用多行注释说明无符号右移运算的底层计算过程
package net.ittimeline.java.core.foundational.operator.bit;
/**
* 无符号右移案例2:操作负数
*
* @author tony [email protected]
* @version 2023/7/21 21:49
* @since Java17
*/
public class UnsignedRightMoveOperatorExample2NegativeNumber {
public static void main(String[] args) {
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充0
1111 1111 1111 1111 1111 1111 1111 0110
>>> 1 二进制位左边加一个0,右边删一个0
=
0111 1111 1111 1111 1111 1111 1111 1011
3.将补码换算成原码
由于0111 1111 1111 1111 1111 1111 1111 1011 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0111 1111 1111 1111 1111 1111 1111 1011
4.将原码转换成十进制
0111 1111 1111 1111 1111 1111 1111 1011转换成十进制的结果是2147483643
因此-10 >>> 2的结果是2147483643
*/
System.out.println("-10 >>> 1 = " + (-10 >>> 1));
/*
1.先求-10的补码
计算机中的数据是使用补码进行计算的
由于-10是负数,最高位(符号位)是1
①计算10的原码
10的原码:0000 0000 0000 0000 0000 0000 0000 1010
②计算-10的原码
-10的原码:1000 0000 0000 0000 0000 0000 0000 1010
③计算机-10的反码
原码求反码:原码最高位不变,其他位取反
-10的反码:1111 1111 1111 1111 1111 1111 1111 0101
④计算-10的补码
反码求补码:补码=反码+1
-10的补码:1111 1111 1111 1111 1111 1111 1111 0110
2. 按照右移的计算规则计算:用于将数据的二进制位向右移动,左边填充0
1111 1111 1111 1111 1111 1111 1111 0110
>>> 2 二进制位左边加两个0,右边删10
=
0011 1111 1111 1111 1111 1111 1111 1101
3.将补码换算成原码
由于0011 1111 1111 1111 1111 1111 1111 1101 左边的最高位是0,表示正数
正数的原码、反码和补码都是一样的
补码转换成原码的结果是0011 1111 1111 1111 1111 1111 1111 1101
4.将原码转换成十进制
0011 1111 1111 1111 1111 1111 1111 1101转换成十进制的结果是1073741821
因此-10 >>> 2的结果是1073741821
*/
System.out.println("-10 >>> 2 = " + (-10 >>> 2));
}
}
程序运行结果
优势:简单、适用性好
缺点:需要开辟临时空间
VariableExchangeWithTempSpace演示基于中间变量实现交换的具体实现过程
class VariableExchangeWithTempSpace {
public static void main(String[] args) {
int left = 10;
int right = 20;
System.out.printf("交换之前\nleft = %d right = %d \n", left, right);
//使用中间变量交换 缺点:需要开辟临时空间 优点:简单、适用性好
int temp = left;
left = right;
right = temp;
System.out.printf("变量交换的方式1:基于中间变量实现交换之后\nleft = %d right = %d \n", left, right);
}
}
程序运行结果
优势:不需要开辟临时空间
缺点:适用性差(不支持非数值类型)、可能超出int类型的范围
VariableExchangeWithArithmetic演示基于算术运算实现变量交换的具体实现过程
值得注意的是加减法可以替换成乘除法也可以实现变量交换
class VariableExchangeWithArithmetic {
public static void main(String[] args) {
int left = 10;
int right = 20;
System.out.printf("交换之前\nleft = %d right = %d \n", left, right);
//使用算术运算交换 不需要临时变量节省空间, 缺点:适用性差(不支持非数值类型)、可能超出int类型的范围
//30 =10+20
left = left + right;
//10=30-20
right = left - right;
//20=30-10
left = left - right;
System.out.printf("变量交换的方式2:基于算术运算(加减法)实现交换之后\nleft = %d right = %d \n", left, right);
}
}
程序运行结果
优势:不需要开辟临时空间
缺点:适用性差(不适用非数值类型)、难以理解和维护
VariableExchangeWithXor演示基于异或运算实现变量交换的具体实现过程
class VariableExchangeWithXor {
public static void main(String[] args) {
int left = 10;
int right = 20;
System.out.printf(“交换之前\nleft = %d right = %d \n”, left, right);
//使用异或实现变量交换 缺点:难 适用性差(不适用非数值类型)
left = left ^ right;
right = left ^ right;
left = left ^ right;
System.out.printf(“变量交换的方式3:基于位运算(按位异或)实现交换之后\nleft = %d right = %d \n”, left, right);
}
}
程序运行结果
经过比较三种变量交换的方式,建议使用方式1:通过中间变量实现变量交换,后续在给数据排序时一些排序算法的实现会使用到变量交换。