胡豆秆

个人博客

欢迎来到我的个人博客~


Java运算符


Java运算符

运算符优先级

​ 所有的数学运算都认为是从左向右运算的,Java 语言中大部分运算符也是从左向右结合的,只有单目运算符、赋值运算符和三目运算符例外,其中,单目运算符、赋值运算符和三目运算符是从右向左结合的,也就是从右向左运算。

​ 乘法和加法是两个可结合的运算,也就是说,这两个运算符左右两边的操作数可以互换位置而不会影响结果。运算符有不同的优先级,所谓优先级就是在表达式运算中的运算顺序。

​ 一般而言,单目运算符优先级较高,赋值运算符优先级较低。算术运算符优先级较高,关系和逻辑运算符优先级较低。多数运算符具有左结合性,单目运算符、三目运算符、赋值运算符具有右结合性。

​ Java 语言中运算符的优先级共分为 14 级,其中 1 级最高,14 级最低。在同一个表达式中运算符优先级高的先执行。

运算符的优先级
优先级 运算符 结合性
1 ()、[]、{} 从左向右
2 !、+、-、~、++、-- 从右向左
3 *、/、% 从左向右
4 +、- 从左向右
5 «、»、>>> 从左向右
6 <、<=、>、>=、instanceof 从左向右
7 ==、!= 从左向右
8 & 从左向右
9 ^ 从左向右
10 | 从左向右
11 && 从左向右
12 || 从左向右
13 ?: 从右向左
14 =、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>= 从右向左

运算符使用

赋值运算符

​ 赋值运算符是指为变量或常量指定数值的符号。

​ 赋值运算符的符号为“=”,它是双目运算符,左边的操作数必须是变量,不能是常量或表达式。

​ 其语法格式为: 变量名称=表达式内容

​ 在 Java 语言中,“变量名称”和“表达式”内容的类型必须匹配,如果类型不匹配则需要自动转化为对应的类型。

​ 赋值运算符的优先级低于算术运算符,结合方向是自右向左;不是数学中的等号,它表示一个动作,即将其右侧的值送到左侧的变量中(左侧只允许是变量,不能是表达式或其他形式);不要将赋值运算符与相等运算符“==”混淆。

​ 赋值运算符与其他运算符一起使用,可以表达多种赋值运算的变异效果。例如,在基本的赋值运算符的基础之上,可以结合算术运算符,以及后面要学习的位运算符,组合成复合的赋值运算符。赋值运算符和算数运算符组成的复合赋值运算的含义及其使用实例如下表所示。

赋值运算符和算数运算符组成的复合赋值运算的含义及其使用实例
运算符 含义 实例 结果
+= 将该运算符左边的数值加上右边的数值, 其结果赋值给左边变量本身 int a=5; a+=2; a=7
-= 将该运算符左边的数值减去右边的数值, 其结果赋值给左边变量本身 int a=5; a-=2; a=3
*= 将该运算符左边的数值乘以右边的数值, 其结果赋值给左边变量本身 int a=5; a*=2; a=10
/= 将该运算符左边的数值整除右边的数值, 其结果赋值给左边变量本身 int a=5; a/=2; a=2
%= 将该运算符左边的数值除以右边的数值后取余,其结果赋值给左边变量本身 int a=5; a%=2; a=1
int x, y, z; // 定义3个整型的变量
x = y = z = 5; // 为变量赋初值为5
x += 10; // 等价于x=x+10,结果x=15
y -= 3; // 等价于y=y-3,结果y=2
z *= 5; // 等价于z=z*5,结果z=25
x /= 4; // 等价于x=x/4,结果x=3
z %= x; // 等价于z=z%x,结果z=1

​ 说到赋值运算,让我想到了之前同学的一个面试题:

public class MethodTest {
	static int a;
	static int b;
	
	public static void main(String args[]) {
		method(1,2);
	}
	
	private static void method(int x,int y) {
		//使用一句代码,把x和y的值分别赋给a和b
	    //即将a = x; b = y; 合为一句代码使得输出: a:1 b:2
        System.out.println("a:" + a + " b:" + b);
	}
}

​ 当时听到这个题其实是没有理解到他的考点的,不过后来想到了赋值运算符,才知道了他的考点。答案并不固定,你们可以自己试试,尝试不同的答案及不同的数量。以下是我的答案:


算术运算符

​ 运算符丰富是 Java 语言的主要特点之一,它提供的运算符数量之多,在高级语言中是少见的。

​ Java 语言中的运算符除了具有优先级之外,还有一个结合性的特点。当一个表达式中出现多种运算符时,执行的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的约束,以便确定是自左向右进行运算还是自右向左进行运算。这些运算符按照操作数的数量可以分为单目运算符、双目运算符和三目运算符。

​ Java 中的算术运算符主要用来组织数值类型数据的算术运算,按照参加运算的操作数的不同可以分为一元运算符和二元运算符。

一元运算符

​ 算术一元运算一共有 3 个,分别是 -、++ 和 –。具体说明参见下表:

一元算术运算
运 算 符 名 称 说 明 例 子
取反符号 取反运算 b=-a
++ 自加一 先取值再加一,或先加一再取值 a++ 或 ++a
-- 自减一 先取值再减一,或先减一再取值 a-- 或 --a
public static void main(String args[]) {
    int i = 1;
    System.out.println(i ++);//先取值在加1 打印1 i变为2
    System.out.println(i --);//先取值在减1 打印2 i变为1
    System.out.println(++ i);//先加1在取值 打印2 i变为2
    System.out.println(-- i);//先减1在取值  打印1 i变为1
    System.out.println(- i);//取i的负数即-1 打印-1 i还是1
    System.out.println(-i ++);//先取负数-1 打印-1 i变为2
    System.out.println(-i --);//先取负数-2 打印-2 i变为1
    //++ -i 或 -- -i 会出现编译时错误Invalid argument to operation ++/--
    System.out.println(i);
}

执行结果如下:


二元运算符

​ Java 语言中算术运算符的功能是进行算术运算,除了经常使用的加(+)、减(-)、乘(*)和除(\)外,还有取模运算(%)。具体说明参见下表 。

二元算术运算
运 算 符 名 称 说 明 例 子
+ 求 a 加 b 的和,还可用于 String 类型,进行字符串连接操作 a + b
- 求 a 减 b 的差 a - b
* 求 a 乘以 b 的积 a * b
求 a 除以 b 的商 a / b
%
取余 求 a 除以 b 的余数  a % b
public static void main(String args[]) {
    int a = 1;
    int b = 2;
    System.out.println(a + b);//3
    System.out.println(a - b);//-1
    System.out.println(a * b);//2
    System.out.println(a / b);//0 注 1 ÷ 2 = 0.5 去掉小数点变为0
    System.out.println(a % b);//1 注 1 ÷ 2 取余为 1
    System.out.println(a + b - a * b / a % b);//3  注 * / % 优先级大于 + -
    System.out.println("" + a + b);// 12 注 在涉及字符串的+运算中 运算就变为了字符串拼接
    //字符串在与整形做 - * / % 运算时会出现编译时错误 The operator -,*,/,% is undefined for the argument type(s) String, int
    System.out.println("" + a * b);// 2 注 * / % 优先级大于 + - 先计算a * b结果 再与字符串拼接
}

运行结果如下:


逻辑运算符

​ 逻辑运算符把各个运算的关系表达式连接起来组成一个复杂的逻辑表达式,以判断程序中的表达式是否成立,判断的结果是 true 或 false。

​ 逻辑运算符是对布尔型变量进行运算,其结果也是布尔型,具体如下表所示:

逻辑运算符的用法、含义及实例
运算符 用法 含义 说明 实例 结果
&& a&&b 短路与 ab 全为 true 时,计算结果为 true,否则为 false。 2>1&&3<4 true
|| a||b 短路或 ab 全为 false 时,计算结果为 false,否则为 true。 2<1||3>4 false
! !a 逻辑非 a 为 true 时,值为 false,a 为 false 时,值为 true !(2>4) true
| a|b 逻辑或 ab 全为 false 时,计算结果为 false,否则为 true 1>2|3>5 false
& a&b 逻辑与 ab 全为 false 时,计算结果为 false,否则为 true 1<2&3<5 true
	//回顾这篇博客的时候,发现博客在展示的时候把 | 和 || 解析成了表格的框。
	//使得包含了 | 和 || 的文字部分都被表格框起来了。
	//不知道是什么原因,所以使用了代码框把包含了 | 和 || 的文字部分框起来了。
	//这样可能会影响博客的阅读,不好意思。好消息是没有包含 | 和 || 的文字部分可以正常展示。
	逻辑运算符的优先级为:!运算级别最高,&& 运算高于 || 运算。
	!运算符的优先级高于算术运算符,而 && 和 || 运算则低于关系运算符。
	结合方向是:逻辑非(单目运算符)具有右结合性,逻辑与和逻辑或(双目运算符)具有左结合性。


​ 顺便说一下遇到的逻辑运算符面试题。以下代码输出的结果是:

public static void main(String args[]) {
    System.out.println(true || false && false);
}
	这个题的考点就是逻辑运算符的优先级。
	我第一次看到这个题的解题思路就是:true || false 结果是true,那么后面就是true && false 结果为false。
	这种解题思路就是错的。虽然大多运算符的执行顺序都是从左往右,但&& 的优先级高于 ||。
	所以,这道题的正确顺序应该是:false && false 结果是false,true || false 结果为true。

	但是,这道题的正确解题思路应该是:||之前为true,那么整个表达式就为true;
	&&之前为false,那么整个表达式就为false。
	那么这就是我遇到过了另一个面试题了:| & 和 || && 的区别?
	
	关于| & 和 || && 的区别,我的个人理解为:| & 在判断结果时,会判断它们前后两个表达式的true false;
	而|| &&在判断结果时,如果||之前为true,那么整个表达式就为true;
	&&之前为false,那么整个表达式就为false。
	也就是说,如果||之前为true,那么它就不会再执行它后面的判断语句;
	同理,若&&前为false,也不会再执行之后的语句。

public static void main(String args[]) {
    //设置i,j值为0
    int i = 0;
    int j = 0;
    //使用以下语句,如果之后i,j都被赋值,说明两个赋值语句都被执行
    //如果i没被赋值,则说明后面的语句并没有被执行
    System.out.println(((j = 1) == 1) | ((i = 1) == 1));
    System.out.println("j:" + j + " i:" + i);
    //i,j重新赋值为0
    //同理
    i = 0;
    j = 0;
    System.out.println(((j = 1) != 1) & ((i = 1) != 1));
    System.out.println("j:" + j + " i:" + i);
    i = 0;
    j = 0;
    System.out.println(((j = 1) == 1) || ((i = 1) == 1));
    System.out.println("j:" + j + " i:" + i);
    i = 0;
    j = 0;
    System.out.println(((j = 1) != 1) && ((i = 1) != 1));
    System.out.println("j:" + j + " i:" + i);
}

运行结果如下:

	运行结果显示,使用 | , & 的语句,i , j 都被赋值,
	而使用 || , && 的语句,i 却没有被赋值,说明它并没有之后之后的语句。
	这就是 | & 和 || && 使用上的区别。


Java关系运算符

​ 关系运算符(relational operators)也可以称为“比较运算符”,用于用来比较判断两个变量或常量的大小。关系运算符是二元运算符,运算结果是 boolean 型。当运算符对应的关系成立时,运算结果是 true,否则是 false。

​ 关系表达式是由关系运算符连接起来的表达式。关系运算符中“关系”二字的含义是指一个数据与另一个数据之间的关系,这种关系只有成立与不成立两种可能情况,可以用逻辑值来表示,逻辑上的 true 与 false 用数字 1 与 0 来表示。关系成立时表达式的结果为 true(或 1),否则表达式的结果为 false(或 0)。

比较运算符的含义及其实例应用
运算符 含义 说明 实例 结果
> 大于运算符 只支持左右两边操作数是数值类型。如果前面变量的值大于后面变量的值, 则返回 true。 2>3 false
>= 大于或等于运算符 只支持左右两边操作数是数值类型。如果前面变量的值大于等于后面变量的值, 则返回 true。 4>=2 true
< 小于运算符 只支持左右两边操作数是数值类型。如果前面变量的值小于后面变量的值,则返回 true。 2<3 true
<= 小于或等于运算符 只支持左右两边操作数是数值类型。如果前面变量的值小于等于后面变量的值, 则返回 true。 4<=2 false
== 相等运算符 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。
如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。
Java 也支持两个 boolean 类型的值进行比较。
4==4
97=='a'
5.0==5
true==false
true
true
true
false
!= 不相等运算符 如果进行比较的两个操作数都是数值类型,无论它们的数据类型是否相同,只要它们的值不相等,也都将返回 true。
如果两个操作数都是引用类型,只有当两个引用变量的类型具有父子关系时才可以比较,只要两个引用指向的不是同一个对象就会返回 true。
4!=2 true

注意点如下所示:

  • 基本类型的变量、值不能和引用类型的变量、值使用 == 进行比较;boolean 类型的变量、值不能与其他任意类型的变量、值使用 == 进行比较;如果两个引用类型之间没有父子继承关系,那么它们的变量也不能使用 == 进行比较。
  • == 和 != 可以应用于基本数据类型和引用类型。当用于引用类型比较时,比较的是两个引用是否指向同一个对象,但当时实际开发过程多数情况下,只是比较对象的内容是否相当,不需要比较是否为同一个对象。

关系表达式通常用于 Java 程序的逻辑判断语句的条件表达式中。使用关系表达式要注意以下几点:

  • 运算符 >=、==、!=、<= 是两个字符构成的一个运算符,用空格从中分开写就会产生语法错误。例如 x> =y; 是错误的,但是可以写成 x>=y; 在运算符的两侧增加空格会提高可读性。同样将运算符写反,例如 =>、=<、=! 等形式会产生语法错误。
  • 由于计算机内存放的实数与实际的实数存在着一定的误差,如果对浮点数进行 ==(相等)或 !=(不相等)的比较,容易产生错误结果,应该尽量避免。
  • 不要将“==”写成“=”。

​ 说到==,我想起了一个面试题:==和equals()方法的区别?

​ ==如果是比较两个基本类型值(如int,double等),则是比较这两个值是否相等;如果是比较两个引用类型,则是比较两个引用对象的地址是否相等。equals()是Object的方法,大多子类都有重写这个方法,Object中的equals()方法内部实现就是使用的==来做地址判断。

//Object类中的equals方法
public boolean equals(Object obj) {
    return (this == obj);
}

​ Object的各个子类重写后的equsal()方法可能各有不同,如Integer和Long类的equals()方法如下:

//Integer类
public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}
//Long类
public boolean equals(Object obj) {
    if (obj instanceof Long) {
        return value == ((Long)obj).longValue();
    }
    return false;
}

​ 判断传入对象是否是当前类对象,或其子类。如不是则返回false,否则则使用==来判断两个值是否相等。


Java位运算符

​ Java 定义的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括 long,int,short,char 和 byte。

​ 位运算符主要用来对操作数二进制的位进行运算。按位运算表示按每个二进制位(bit)进行计算,其操作数和运算结果都是整型值

位逻辑运算符

​ 位逻辑运算符包含 4 个:&(与)、 (或)、~(非)和 ^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符。
位逻辑运算符
运算符 含义 实例 结果
& 按位进行与运算(AND) 4 & 5 4
| 按位进行或运算(OR) 4 | 5 5
^ 按位进行异或运算(XOR) 4 ^ 5 1
~ 按位进行取反运算(NOT) ~ 4 -5
&

​ 位与运算符,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么计算结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。有0为0。

|

​ 位或运算符,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1;如果对应的二进制位都为 0,结果才为 0。有1为1。

^

​ 位异或运算符,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。相同为0,不同为1。

~

​ 位取反运算符,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。1变0,0变1。十进制取反的规律是:加1取负

public static void main(String args[]) {
int i = 0b1011;//11
int j = 0b1010;//10
int k = 0b0111;//7
System.out.println("&&&&&&&&&&&&&&&&");
System.out.println(i & j);//1010 => 10
System.out.println(i & k);//0011 => 3
System.out.println(j & k);//0010 => 2
System.out.println("||||||||||||||||");
System.out.println(i | j);//1011 => 11
System.out.println(i | k);//1111 => 15
System.out.println(j | k);//1111 => 15
System.out.println("^^^^^^^^^^^^^^^^");
System.out.println(i ^ j);//0001 => 1
System.out.println(i ^ k);//1100 => 12
System.out.println(j ^ k);//1101 => 13
System.out.println("~~~~~~~~~~~~~~~~");
System.out.println(~i);//1111 1111 1111 1111 1111 1111 1111 0100 => -12
System.out.println(~j);//1111 1111 1111 1111 1111 1111 1111 0101 => -11
System.out.println(~k);//1111 1111 1111 1111 1111 1111 1111 1000 => -8
}

运行结果如下:

​ 注意:位运算符的操作数只能是整型或者字符型数据以及它们的变体,不用于 float、double 或者 long 等复杂的数据类型。


位移运算符

​ 位移运算符用来将操作数向某个方向(向左或者右)移动指定的二进制位数。下表是 Java 语言中的两个位移运算符,它们都属于双目运算符。

位移运算符
运算符 含义 实例 结果
» 右移位运算符 8»1 4
« 左移位运算符 9«2 36
«

​ 左移位运算符,其运算规则是:按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。左移,低位补零。

»

​ 右位移运算符为»,其运算规则是:按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补零。右移,高位补零。

public static void main(String args[]) {
    int i = 0b1011;//0000 0000 0000 0000 0000 0000 0000 1011 => 11
    int j = 0b1010;//0000 0000 0000 0000 0000 0000 0000 1010 => 10
    int k = 0b0111;//0000 0000 0000 0000 0000 0000 0000 0111 => 7
    System.out.println(i << 2);//00 0000 0000 0000 0000 0000 0000 1011 00 => 44
    System.out.println(j << 3);//0 0000 0000 0000 0000 0000 0000 1010 000 => 80
    System.out.println(k << 4);//0000 0000 0000 0000 0000 0000 0111 0000 => 112
    System.out.println(i >> 2);//00 0000 0000 0000 0000 0000 0000 0000 10 => 2
    System.out.println(j >> 3);//000 0000 0000 0000 0000 0000 0000 0000 1 => 1
    System.out.println(k >> 4);//0000 0000 0000 0000 0000 0000 0000 0000 => 0
}

执行结果如下:

复合位赋值运算符

​ 所有的二进制位运算符都有一种将赋值与位运算组合在一起的简写形式。复合位赋值运算符由赋值运算符与位逻辑运算符和位移运算符组合而成。

复合位赋值运算符
运算符 含义 实例 结果
&= 按位与赋值 num1 &= num2 等价于 num 1=num 1 & num2
|= 按位或赋值 num1 |= num2 等价于 num 1=num 1 | num2
^= 按位异或赋值 num1 ^= num2 等价于 num 1=num 1 ^ num2
-= 按位取反赋值 num1 ~= num2 等价于 num 1=num 1 ~ num2
«= 按位左移赋值 num1 «= num2 等价于 num 1=num 1 « num2
»= 按位右移赋值 num1 »= num2 等价于 num 1=num 1 » num2

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦