operator.md 12.8 KB
Newer Older
沉默王二's avatar
沉默王二 已提交
1
---
2 3
title: Java 运算符
shortTitle: Java 运算符
沉默王二's avatar
沉默王二 已提交
4
category:
沉默王二's avatar
沉默王二 已提交
5
  - Java核心
沉默王二's avatar
沉默王二 已提交
6
tag:
沉默王二's avatar
沉默王二 已提交
7 8
  - Java语法基础
description: Java程序员进阶之路,小白的零基础Java教程,本文主要介绍Java 中的运算符(算术运算符、关系运算符、赋值运算符、逻辑运算符、位运算符)的使用
9 10 11
head:
  - - meta
    - name: keywords
沉默王二's avatar
沉默王二 已提交
12
      content: Java,Java SE,Java基础,Java教程,Java程序员进阶之路,Java入门,教程,运算符
沉默王二's avatar
沉默王二 已提交
13 14
---

沉默王二's avatar
doc  
沉默王二 已提交
15 16 17 18
“二哥,让我盲猜一下哈,运算符是不是指的就是加减乘除啊?”三妹的脸上泛着甜甜的笑容,我想她一定对提出的问题很有自信。

“是的,三妹。运算符在 Java 中占据着重要的位置,对程序的执行有着很大的帮助。除了常见的加减乘除,还有许多其他类型的运算符,来看下面这张思维导图。”

沉默王二's avatar
沉默王二 已提交
19
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/core-grammar/eleven-01.png)
沉默王二's avatar
doc  
沉默王二 已提交
20 21


沉默王二's avatar
沉默王二 已提交
22
## 01、算数运算符
沉默王二's avatar
doc  
沉默王二 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

算术运算符除了最常见的加减乘除,还有一个取余的运算符,用于得到除法运算后的余数,来串代码感受下。

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class ArithmeticOperator {
    public static void main(String[] args) {
        int a = 10;
        int b = 5;

        System.out.println(a + b);//15
        System.out.println(a - b);//5
        System.out.println(a * b);//50
        System.out.println(a / b);//2
        System.out.println(a % b);//0

        b = 3;
        System.out.println(a + b);//13
        System.out.println(a - b);//7
        System.out.println(a * b);//30
        System.out.println(a / b);//3
        System.out.println(a % b);//1
    }
}
```

对于初学者来说,加法(+)、减法(-)、乘法(*)很好理解,但除法(/)和取余(%)会有一点点疑惑。在以往的认知里,10/3 是除不尽的,结果应该是 3.333333...,而不应该是 3。相应的,余数也不应该是 1。这是为什么呢?

沉默王二's avatar
沉默王二 已提交
53
因为数字在程序中可以分为两种,一种是整型,一种是浮点型(不清楚的同学可以回头看看[数据类型那篇](https://tobebetterjavaer.com/basic-grammar/basic-data-type.html)),整型和整型的运算结果就是整型,不会出现浮点型。否则,就会出现浮点型。
沉默王二's avatar
doc  
沉默王二 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class ArithmeticOperator {
    public static void main(String[] args) {
        int a = 10;
        float c = 3.0f;
        double d = 3.0;
        System.out.println(a / c); // 3.3333333
        System.out.println(a / d); // 3.3333333333333335
        System.out.println(a % c); // 1.0
        System.out.println(a % d); // 1.0
    }
}
```

需要注意的是,当浮点数除以 0 的时候,结果为 Infinity 或者 NaN。

```
System.out.println(10.0 / 0.0); // Infinity
System.out.println(0.0 / 0.0); // NaN
```

Infinity 的中文意思是无穷大,NaN 的中文意思是这不是一个数字(Not a Number)。


当整数除以 0 的时候(`10 / 0`),会抛出异常:

```
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at com.itwanger.eleven.ArithmeticOperator.main(ArithmeticOperator.java:32)
```

所以整数在进行除法运算时,需要先判断除数是否为 0,以免程序抛出异常。

算术运算符中还有两种特殊的运算符,自增运算符(++)和自减运算符(--),它们也叫做一元运算符,只有一个操作数。

```java
public class UnaryOperator1 {
    public static void main(String[] args) {
        int x = 10;
        System.out.println(x++);//10 (11)  
        System.out.println(++x);//12  
        System.out.println(x--);//12 (11)  
        System.out.println(--x);//10  
    }
}
```

一元运算符可以放在数字的前面或者后面,放在前面叫前自增(前自减),放在后面叫后自增(后自减)。

前自增和后自增是有区别的,拿 `int y = ++x` 这个表达式来说(x = 10),它可以拆分为 `x = x+1 = 11; y = x = 11`,所以表达式的结果为 `x = 11, y = 11`。拿 `int y = x++` 这个表达式来说(x = 10),它可以拆分为 `y = x = 10; x = x+1 = 11`,所以表达式的结果为 `x = 11, y = 10`

```java
int x = 10;
int y = ++x;
System.out.println(y + " " + x);// 11 11

x = 10;
y = x++;
System.out.println(y + " " + x);// 10 11
```

对于前自减和后自减来说,同学们可以自己试一把。


沉默王二's avatar
沉默王二 已提交
122
## 02、关系运算符
沉默王二's avatar
doc  
沉默王二 已提交
123 124 125

关系运算符用来比较两个操作数,返回结果为 true 或者 false。

沉默王二's avatar
沉默王二 已提交
126
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/core-grammar/eleven-02.png)
沉默王二's avatar
doc  
沉默王二 已提交
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146

来看示例:

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class RelationOperator {
    public static void main(String[] args) {
        int a = 10, b = 20;
        System.out.println(a == b); // false
        System.out.println(a != b); // true
        System.out.println(a > b); // false
        System.out.println(a < b); // true
        System.out.println(a >= b); // false
        System.out.println(a <= b); // true
    }
}
```

沉默王二's avatar
沉默王二 已提交
147
## 03、位运算符
沉默王二's avatar
doc  
沉默王二 已提交
148

沉默王二's avatar
沉默王二 已提交
149
在学习位运算符之前,需要先学习一下二进制,因为位运算符操作的不是整型数值(int、long、short、char、byte)本身,而是整型数值对应的二进制。
沉默王二's avatar
doc  
沉默王二 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class BitOperator {
    public static void main(String[] args) {
        System.out.println(Integer.toBinaryString(60)); // 111100
        System.out.println(Integer.toBinaryString(13)); // 1101
    }
}
```

 从程序的输出结果可以看得出来,60 的二进制是 0011 1100(用 0 补到 8 位),13 的二进制是 0000 1101。

PS:现代的二进制记数系统由戈特弗里德·威廉·莱布尼茨于 1679 年设计。莱布尼茨是德意志哲学家、数学家,历史上少见的通才。

沉默王二's avatar
沉默王二 已提交
167
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/core-grammar/eleven-03.png)
沉默王二's avatar
doc  
沉默王二 已提交
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

来看示例:

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class BitOperator {
    public static void main(String[] args) {
        int a = 60, b = 13;
        System.out.println("a 的二进制:" + Integer.toBinaryString(a)); // 111100
        System.out.println("b 的二进制:" + Integer.toBinaryString(b)); // 1101

        int c = a & b;
        System.out.println("a & b:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = a | b;
        System.out.println("a | b:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = a ^ b;
        System.out.println("a ^ b:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = ~a;
        System.out.println("~a:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = a << 2;
        System.out.println("a << 2:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = a >> 2;
        System.out.println("a >> 2:" + c + ",二进制是:" + Integer.toBinaryString(c));

        c = a >>> 2;
        System.out.println("a >>> 2:" + c + ",二进制是:" + Integer.toBinaryString(c));
    }
}
```

对于初学者来说,位运算符无法从直观上去计算出结果,不像加减乘除那样。因为我们日常接触的都是十进制,位运算的时候需要先转成二进制,然后再计算出结果。

鉴于此,初学者在写代码的时候其实很少会用到位运算。对于编程高手来说,为了提高程序的性能,会在一些地方使用位运算。比如说,HashMap 在计算哈希值的时候:

```java
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
```

如果对位运算一点都不懂的话,遇到这样的源码就很吃力。所以说,虽然位运算用的少,但还是要懂。

1)按位左移运算符:

```java
public class LeftShiftOperator {
    public static void main(String[] args) {
        System.out.println(10<<2);//10*2^2=10*4=40  
        System.out.println(10<<3);//10*2^3=10*8=80  
        System.out.println(20<<2);//20*2^2=20*4=80  
        System.out.println(15<<4);//15*2^4=15*16=240  
    }
}
```

`10<<2` 等于 10 乘以 2 的 2 次方;`10<<3` 等于 10 乘以 2 的 3 次方。

2)按位右移运算符:

```java
public class RightShiftOperator {
    public static void main(String[] args) {
        System.out.println(10>>2);//10/2^2=10/4=2
        System.out.println(20>>2);//20/2^2=20/4=5
        System.out.println(20>>3);//20/2^3=20/8=2
    }
}
```

`10>>2` 等于 10 除以 2 的 2 次方;`20>>2` 等于 20 除以 2 的 2 次方。

沉默王二's avatar
沉默王二 已提交
247
## 04、逻辑运算符
沉默王二's avatar
doc  
沉默王二 已提交
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

逻辑与运算符(&&):多个条件中只要有一个为 false 结果就为 false。

逻辑或运算符(||):多个条件只要有一个为 true 结果就为 true。

```java
public class LogicalOperator {
    public static void main(String[] args) {
        int a=10;
        int b=5;
        int c=20;
        System.out.println(a<b&&a<c);//false && true = false

        System.out.println(a>b||a<c);//true || true = true
    }
}
```

沉默王二's avatar
沉默王二 已提交
266
逻辑非运算符(!):用来反转条件的结果,如果条件为 true,则逻辑非运算符将得到 false。
沉默王二's avatar
doc  
沉默王二 已提交
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

单逻辑与运算符(&):很少用,因为不管第一个条件为 true 还是 false,依然会检查第二个。

单逻辑或运算符(|):也会检查第二个条件。

也就是说,& 和 | 性能不如 && 和 ||,但用法一样:

```java
public class LogicalOperator1 {
    public static void main(String[] args) {
        int a=10;
        int b=5;
        int c=20;
        System.out.println(a<b&a<c);//false & true = false

        System.out.println(a>b|a<c);//true | true = true  
    }
}
```

沉默王二's avatar
沉默王二 已提交
287
## 05、赋值运算符
沉默王二's avatar
doc  
沉默王二 已提交
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

赋值操作符恐怕是 Java 中使用最频繁的操作符了,它就是把操作符右侧的值赋值给左侧的变量。来看示例:

```java
public class AssignmentOperator {
    public static void main(String[] args) {
        int a=10;
        int b=20;
        a+=4;//a=a+4 (a=10+4)  
        b-=4;//b=b-4 (b=20-4)  
        System.out.println(a);
        System.out.println(b);
    }
}
```

不过在进行数值的赋值时,需要小点心,比如说下面这种情况:

沉默王二's avatar
沉默王二 已提交
306
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/core-grammar/eleven-04.png)
沉默王二's avatar
doc  
沉默王二 已提交
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

编译器之所以提示错误,是因为 = 右侧的算术表达式默认为 int 类型,左侧是 short 类型的时候需要进行强转。

```java
public class AssignmentOperator1 {
    public static void main(String[] args) {
        short a = 10;
        short b = 10;
//a+=b;//a=a+b internally so fine
        a = (short)(a + b);
        System.out.println(a);
    }
}
```

除此之外,还会有边界问题,比如说,两个非常大的 int 相乘,结果可能就超出了 int 的范围:

```java
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class BigIntMulti {
    public static void main(String[] args) {
        int a = Integer.MAX_VALUE;
        int b = 10000;
        int c = a * b;
        System.out.println(c); // -10000
    }
}
```

程序输出的结果为 -10000,这个答案很明显不是我们想要的结果,虽然可以通过右侧表达式强转 long 的方法解决:

```
/**
 * 微信搜索「沉默王二」,回复 Java
 */
public class BigIntMulti {
    public static void main(String[] args) {
        int a = Integer.MAX_VALUE;
        int b = 10000;
        long c = (long)a * b;
        System.out.println(c); // 21474836470000
    }
}
```

但尽量不要这样做,结果非常大的时候,尽量提前使用相应的类型进行赋值。

```java
long a = Integer.MAX_VALUE - 1;
long b = 10000;
long c = a * b;
System.out.println(c); // 21474836460000
```

沉默王二's avatar
沉默王二 已提交
363
## 06、三元运算符
沉默王二's avatar
doc  
沉默王二 已提交
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381

三元运算符用于替代 if-else,可以使用一行代码完成条件判断的要求。来看示例:

```java
public class TernaryOperator {
    public static void main(String[] args) {
        int a=2;
        int b=5;
        int min=(a<b)?a:b;
        System.out.println(min);
    }
}
```

如果 ? 前面的条件为 true,则结果为 : 前的值,否则为 : 后的值。

“好了,三妹,关于 Java 运算符就先说这么多吧,你是不是已经清楚了?”转动了一下僵硬的脖子后,我对三妹说。

沉默王二's avatar
jvm  
沉默王二 已提交
382 383
“差不多,二哥,我需要写点 demo 练习会。”

沉默王二's avatar
沉默王二 已提交
384 385 386

---

沉默王二's avatar
沉默王二 已提交
387
最近整理了一份牛逼的学习资料,包括但不限于Java基础部分(JVM、Java集合框架、多线程),还囊括了 **数据库、计算机网络、算法与数据结构、设计模式、框架类Spring、Netty、微服务(Dubbo,消息队列) 网关** 等等等等……详情戳:[可以说是2022年全网最全的学习和找工作的PDF资源了](https://tobebetterjavaer.com/pdf/programmer-111.html)
沉默王二's avatar
沉默王二 已提交
388 389 390

关注二哥的原创公众号 **沉默王二**,回复**111** 即可免费领取。

沉默王二's avatar
沉默王二 已提交
391
![](http://cdn.tobebetterjavaer.com/tobebetterjavaer/images/xingbiaogongzhonghao.png)