「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战」。
前言
在上班摸鱼的时候,就想着来数一数 Java 中有多少运算符,意外发现了我遗漏的 Java 运算符,于是我决定写这篇文章来归类一下所有 Java 运算符。
Java 运算符主要有以下几种分类:
- 关系运算符(>,<,==,!=,>=,<=)
- 位运算符(&,|,^,~,<<,>>,>>>)
- 算数运算符(+,++,-,--,*,/,%)
- 逻辑运算符(&&,&,||,|,!)
- 赋值运算符(=,+=...)
- 其他运算符(?:,.)
关系运算符
关系运算符(>,<,==,!=,>=,<=)是用来比对两个元素值(整型或者字符)的大小,根据比较返回一个布尔类型,主要都是两元运算符。
通常这些元素只能是Java 基础类型,不包括布尔(返回值就是布尔),字符是需要参照 ASCII 编码或者 Unicode 编码,把字符转成数值然后参与比较,其他的类型直接参与比较。
不同的数据类型之间会存在数据类型之间的转换,这里主要是比较数值,不考虑精度的丢失,所以后面再展开讲解。
这些符号的逻辑是怎么样的,怎么判定返回结果,相信大家看一看就会了。
| 符号 | 含义 |
|---|---|
| 当在符号前面的数(下文简称前者)大于符号后面的数(下文简称后者)时,返回结果为 true,反之为 false | |
| < | 当前者小于后者时,返回结果为 true,反之为 false |
| == | 当前者等于后者时,返回结果为 true,反之为 false |
| != | 当前者不等于后者时,返回结果为 true,反之为 false |
| >= | 当前者大于或者等于后者时,返回结果为 true,反之为 false |
| <= | 当前者小于或者等于后者时,返回结果为 true,反之为 false |
以下为运行代码:
System.out.println(1<2); //true
System.out.println(1<=2); //true
System.out.println(1>2); //false
System.out.println(1>=2); //false
System.out.println(1==2); //false
System.out.println(1!=2); //true
System.out.println('1'<'2'); //true
System.out.println(3.14F<'2'); //true
System.out.println(3.14F<'2'); //true
System.out.println(3.14F<4L); //true
位运算符
位运算符(&,|,^,~,<<,>>,>>>)是对比特位进行操作的一种运算符,可以使用该运算符的数据类型为整型或字符,返回的数据类型是整型,基本都是两元运算符。
在 Java 中,整型可以使用 2、8、10、16 进制表示。
- 二进制:以 0B 或者 0b 开头。
- 八进制:以 0 开头。
- 十进制:不能以 0 开头,就平常的数字。
- 十六进制:以 0X 或者 0x 开头。
我们再人工运算位运算时,得把十进制的数字用二进制表示出来,然后一位一位数去对比。
(7)10 = (111)2
| 符号 | 含义 |
|---|---|
| & | 与运算。两个比特位同为 1,结果为 1,否则为 0。 |
| | | 或运算。两个比特位任意一个为 1,结果为 1,否则为 0。 |
| 异或运算。两个比特位相同时,结果为 1,否则为 0。 | |
| ~ | 取反运算。这是一个一元运算符,反转比特位,1 变为 0,0变为 1。 |
| << | 左移。把二进制数往左移动,每移动一位,最右边的一位补 0,该操作符右边的数是要移动的位数。 |
| >> | 右移。把二进制数往右移动,每移动一位,最左边的一位是啥就补啥,该操作符右边的数是要移动的位数。 |
| >>> | 无符号右移。这个跟右移一样,只不过最左边一位补的是 0。 |
int a = 0B0111;
int b = 0B1001;
System.out.println(Integer.toBinaryString(a&b));
System.out.println(Integer.toBinaryString(a|b));
System.out.println(Integer.toBinaryString(a^b));
System.out.println(Integer.toBinaryString(a<<2));
System.out.println(Integer.toBinaryString(b>>2));
System.out.println(Integer.toBinaryString(b>>>2));
/**
1
1111
1110
11100
10
10
*/
算数运算符
算数运算符(+,++,-,--,*,/,%)主要是对整型进行运算,也可以运算字符,返回的是一个整型。
加减乘除,小学算术了。
| 符号 | 含义 |
|---|---|
| + | 加法、求正。当 + 在一个数前面时,表示获取这个数的正数,然而实际上没啥作用。 |
| - | 减法、求负。当 - 在一个数前面时,表示获取这个数的负数,就是正数变成负数,负数变成正数。 |
| ++ | 自增。 a++等同于a = a + 1; |
| -- | 自减。a--等同于a = a -1; |
| * | 乘法。 |
| / | 除法。 |
| % | 求余数。a % b = a - (a/b)b |
int c = 1;
int d = 2;
System.out.println(c+d);
System.out.println(c-d);
System.out.println(3*2);
System.out.println(10/2);
System.out.println(10%2);
System.out.println(c++);
// 打印后 c 已经自增了
System.out.println(++c);
System.out.println(c--);
// 打印完后 c 已经自减
System.out.println(--c);
/**
3
-1
6
5
0
1
3
3
1
*/
这里还会涉及到类型转换的问题,这里贴一个Java核心技术卷的图。
在不同的类型数据进行运算时,会按照类型的等级,把等级低的数据转换成高的再开始计算。
我在这里简单总结一下数据类型的等级:byte > short / char > int > long > float > double。更加详细地可以参考上图,实线代表没有精度丢失,虚线会丢失精度。
逻辑运算符
逻辑运算符(&&,&,||,|,!)是对布尔值进行运算,返回一个布尔值。
看到 &、|、^,你可能会说这不是位运算符吗?怎么会归类到逻辑运算符?
这三个符号确实也可以对布尔值进行运算,要知道在 c/c++ 中,true 的值为 1,false 的值为 0,只不过在 java 中 true 是 true,false 是 false,但仍然支持使用位运算符来运算布尔值。
与 &&、|| 不同的是,&、| 不存在断位。
| 符号 | 含义 | ||
|---|---|---|---|
| & | 逻辑与。同位运算符的 & 类似,符号两边的都是 true ,结果才为 true,否则为 false。 | ||
| 逻辑或。同位运算符的 | 类似,符号两边任意一个是 true ,结果就为 true,否则为 false。 | ||
| 逻辑异或。同位运算符的 ^ 类似,当符号两边不同时,也就是一个为 true,另一个为 false 时,结果才为 true。 | |||
| ! | 逻辑非。同位运算符的 ~ 类似,把 true 变为 false,把 false 变为 true。 | ||
| && | 断位逻辑与。这也是一个逻辑与,但它还会断位,运算时从左往右,当遇到一个 false 时,就会返回结果为 false,并且不继续往下计算 | ||
| 断位逻辑或。这也是一个逻辑或,同样的它也会断位,运算时从左往右,当遇到一个 true 时,就会返回结果为 true,并且不继续往下计算。 |
System.out.println(!true);
System.out.println(false^true);
System.out.println(false^false);
int i = 0;
System.out.println(i == 0 | i++ != 0);
//会执行后面的 i++
System.out.println("i ="+i);
i = 0;
System.out.println(i == 0 || i++ != 0);
System.out.println("i ="+i);
i = 0;
System.out.println(i != 0 & i++ == 0);
//会执行后面的 i++
System.out.println("i ="+i);
i = 0;
System.out.println(i != 0 && i++ == 0);
System.out.println("i ="+i);
/**
false
true
false
true
i =1
true
i =0
false
i =1
false
i =0
*/
赋值运算符
赋值运算符(=,+=...)运算符号右边的表达式或者方法,把结果赋值给左边的变量。
| 符号 | 含义 |
|---|---|
| = | 把符号右边运算的结果(以下简称结果)赋值给符号左边的变量(以下简称变量)。 |
| += | 变量加上结果,再赋值给变量, a+=n;等同于a = a + n; |
| -= | 变量减结果,再赋值给变量, a-=n;等同于a = a - n; |
| /= | 变量除以结果,再赋值给变量, a/=n;等同于a = a / n; |
| *= | 变量乘结果,再赋值给变量, a*=n;等同于a = a * n; |
| %= | 变量取模于结果,再赋值给变量, a%=n;等同于a = a % n; |
int a = 1;
a+=1;
System.out.println(a);// 2
int b = 1;
b-=1;
System.out.println(b);// 0
int c = 1;
c*=10;
System.out.println(c);// 10
int d = 10;
d/=5;
System.out.println(d);// 2
int e = 10;
e%=3;
System.out.println(e);// 1
其他运算符
其他运算符(?:,.)
三目运算符
Java 中仅有一个三目运算符(三元运算符),那就是?:,这个运算符的作用是简化if,可以让我们的代码变得更加简洁。
用法:
a = A?B:C
A 可以是一个逻辑表达式或者只是单纯的布尔值。
当 A == true 时,返回结果 B。
当 A == false 时,返回结果 C。
相当于
if(A){
a = B;
}else{
a = C;
}
.
.,一个点。在 Java 中.是对象用来连接属性或者方法的符号。
例如如下操作
s.length;
s.toString;
这里会涉及到访问修饰符,就是决定某个属性或者方法是否能够被访问的修饰符。
有以下四种:
- private。私有,仅在本类内部可以见,修饰对象不能是外部类。
- default。默认,也就是什么都不写,修饰对象可以是类、接口、变量、方法。
- protected。保护,包外不可见(情况复杂,后面详细解释),修饰对象可以是类、变量、方法。
- public。开放,全部地方都可见,修饰对象可以是类、接口、变量、方法。
整理为一个表格如下:
| 修饰符 | 本类(访问) | 同包的其他类(访问) | 其他包(访问) | 同包(是否可被继承) | 其他包(是否可被继承) |
|---|---|---|---|---|---|
| private | Y | N | N | N | N |
| default | Y | Y | N | Y | N |
| protected | Y | Y | N | Y | Y |
| public | Y | Y | Y | Y | Y |
这里稍微解释一下,最简单的两个修饰符就是 private 和 public,前者仅有本类内部可以访问,后者所有类都可以访问,这个很简单。
而 default 和 protected 是在同一个包内部和其他包的访问权限有所不同。
简单记一下 protected 和 default。
- 就访问权限而言,在同一个包内就是 public,包内的所有类都可以访问,在其他包就是 private,其他包的所有类都不能访问。
- 但是在继承操作上,protected 和 public 一样,而 default 仅只有包内能够被继承。