大数据技术分享 大数据技术分享
  • 数学基础
  • 数学进阶
  • 编程入门
  • 电子基础
  • 编译原理
  • 数据结构与算法
  • 软件工程
  • 体系结构
  • 操作系统
  • 计算机网络
  • 计算机图形学
  • 设计模式
  • 并行与分布式系统
  • 计算机系统安全
  • Java基础
  • Java集合
  • Java并发
  • Java虚拟机
  • Linux
  • Shell
  • JDBC
  • Maven
  • Nginx
  • Git
  • Web开发
  • Docker
  • Zookeeper
  • Scala
  • Sqoop
  • Flume
  • Kafka
  • 数据清洗
  • HDFS
  • MySQL
  • HBase
  • Redis
  • ClickHouse
  • Hadoop
  • Hive
  • Spark
  • Flink
  • Java面试题
  • 大数据面试题
  • Java项目
  • 大数据项目
  • 推荐系统
  • 机器学习
  • 深度学习
  • 闲聊
  • 读书笔记
归档
  • 数学基础
  • 数学进阶
  • 编程入门
  • 电子基础
  • 编译原理
  • 数据结构与算法
  • 软件工程
  • 体系结构
  • 操作系统
  • 计算机网络
  • 计算机图形学
  • 设计模式
  • 并行与分布式系统
  • 计算机系统安全
  • Java基础
  • Java集合
  • Java并发
  • Java虚拟机
  • Linux
  • Shell
  • JDBC
  • Maven
  • Nginx
  • Git
  • Web开发
  • Docker
  • Zookeeper
  • Scala
  • Sqoop
  • Flume
  • Kafka
  • 数据清洗
  • HDFS
  • MySQL
  • HBase
  • Redis
  • ClickHouse
  • Hadoop
  • Hive
  • Spark
  • Flink
  • Java面试题
  • 大数据面试题
  • Java项目
  • 大数据项目
  • 推荐系统
  • 机器学习
  • 深度学习
  • 闲聊
  • 读书笔记
归档
  • Java基础

    • Java之变量与基本数据类型
    • Java之运算符与流程控制
      • 运算符
        • 算术运算符
        • 赋值运算符
        • 比较运算符
        • 逻辑运算符
        • 位运算符
        • 条件运算符
        • 运算符优先级
      • 流程控制
        • 顺序结构
        • 分支语句
        • if-else
        • switch-case
        • 比较
        • 循环语句
        • for循环
        • while循环
        • do-while循环
        • 嵌套循环
        • break和continue的使用
    • Java数组详解
    • 数组中这些常用算法你掌握了吗?
    • Java面向对象的内存分析
    • Java面向对象之类的成员
    • Java面向对象的三大特征
    • Java面向对象中的关键字
    • Java中Object类的理解和使用
  • Java集合

  • Java并发

  • Java虚拟机

  • Java
  • Java基础
高飞
2020-09-09
目录

Java之运算符与流程控制

今天继续更新Java系列,接着来看下Java运算符和流程控制。

# 运算符

运算符是一种特殊的符号,用以表示数据的运算赋值和比较等。

运算符的分类:

# 按照功能分类如下:
# 算术运算符(7个):+、-、*、/、%、++、--
# 赋值运算符(12个):=、+=、-=、*=、/=、%=、>>=、<<=、>>>=、&=、|=、^=等
# 比较(或关系)运算符(6个):>、>=、<、<=、==、!=
# 逻辑运算符(6个):&、|、^、!、&&、||
# 位运算符(7个):&、|、^、~、<<、>>、>>>
# 条件运算符(1个):(条件表达式)?结果1:结果2
# Lambda运算符(1个):->(第18章时讲解)
1
2
3
4
5
6
7
8

# 算术运算符

举例:

int m = 2;
m = m++;
System.out.println(m);
//先取m的值2放操作数栈,m再自增1,此时m=3,最后把操作数栈中的2赋值给m,故输出m=2
1
2
3
4

# 赋值运算符

赋值运算符 符号解释
+= 将符号左边的值和右边的值进行相加操作,最后将结果赋值给左边的变量
-= 将符号左边的值和右边的值进行相减操作,最后将结果赋值给左边的变量
*= 将符号左边的值和右边的值进行相乘操作,最后将结果赋值给左边的变量
/= 将符号左边的值和右边的值进行相除操作,最后将结果赋值给左边的变量
%= 将符号左边的值和右边的值进行取余操作,最后将结果赋值给左边的变量

举例:

public class MinusTest {
    public static void main(String[] args) {
        //变量值减1
        short s = 10;
        //方法1
        //s = (short)(s - 1);
        //方法2,推荐
        s--; //或者用--s
        //方法3
        s -= 1;
        //变量值减2
        short s1 = 10;
        //方法1
        //s1 = (short)(s1 - 2);
        //方法2,推荐
        s1 -= 2;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 比较运算符

比较运算符的结果都是boolean类型,要么是true要么是false。

>,<,>=,<=只适用于基本数据类型(除boolean类型之外),= =和!=适用于基本数据类型和引用数据类型。

# 逻辑运算符

逻辑运算符操作的都是boolean类型的变量或常量,而且运算的结果也是boolean类型的值。

区分&和&&:

  • 相同点:如果符号左边是true,则二者都执行符号右边的操作
  • 不同点:对于&,如果符号左边是false则继续执行符号右边的操作。对于&&,如果符号左边是false则不再继续执行符号右边的操作
  • 建议:开发中推荐使用&&

区分|和||:

  • 相同点:如果符号左边是false,则二者都执行符号右边的操作
  • 不同点:对于|,如果符号左边是true则继续执行符号右边的操作。对于||,如果符号左边是true则不再继续执行符号右边的操作
  • 建议:开发中推荐使用||

举例:

boolean x = true;
boolean y = false;
short z = 42;
if ((z++ == 42) && (y = true)) {
    z++;
}
if ((x = false) || (++z == 45)) {
    z++;
}
System.out.println("z=" + z); //输出为z=46
1
2
3
4
5
6
7
8
9
10

# 位运算符

位运算符的运算过程都是基于二进制的补码运算。

这里补充下补码的知识: 首先计算机数据的存储是使用二进制补码形式存储,并且最高位是符号位,正数的最高位是0,负数的最高位是1。

正数和负数的原码、反码、补码:

  • 正数的补码与反码、原码一样,称为三码合一
  • 负数的补码与反码、原码不一样
    • 负数的原码:把十进制转为二进制,然后最高位设置为1
    • 负数的反码:在原码的基础上,最高位不变,其余位取反(0变1,1变0)
    • 负数的补码:反码加1

举例: 怎么高效的计算2*8的值:

2 << 3
8 << 1
1
2

交换两个int变量的值,或者String变量的值:

public class BitTest {
    public static void main(String[] args) {
        int m = 10;
        int n = 5;
        System.out.println("m = " + m + ", n = " + n);
	//方法1:容易理解适用于不同数据类型,但是需要额外定义变量
	//int temp = m;
	//m = n;
	//n = temp;
	//方法2:没有额外定义变量,但是可能超出int的范围,只能适用于数值类型
	//m = m + n; //15 = 10 + 5
	//n = m - n;//10 = 15 - 5
	//m = m - n;//5 = 15 - 10
	//方法3:没有额外定义变量,但是不易理解,只能适用于数值类型
	m = m ^ n; 
	n = m ^ n; //(m ^ n) ^ n
	m = m ^ n;
	System.out.println("m = " + m + ", n = " + n);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 条件运算符

格式:(条件表达式)? 表达式1:表达式2

条件表达式是boolean类型的结果,根据boolean的值选择表达式1或表达式2,如果运算后的结果赋给新的变量,要求表达式1和表达式2为同种或兼容的类型。

举例: 今天是周二,十天后是周几:

public class ConditionTest {
    public static void main(String[] args) {
        int week = 2;
        week += 10;
        week %= 7;
        System.out.println("今天是周2,10天以后是周" + (week == 0 ? "日" : week));
    }
}
1
2
3
4
5
6
7
8

# 运算符优先级

运算符有不同的优先级,所谓优先级就是在表达式运算中的运算符顺序。

如下,上一行中的运算符总是优先于下一行的:

# 1括号:`()`、`[]`、`{}`
# 2正负号:`+`、`-`
# 3单元运算符:`++`、`--`、`~`、`!`
# 4乘法、除法、求余:`*`、`/`、`%`
# 5加法、减法:`+`、`-`
# 6移位运算符:`<<`、`>>`、`>>>`
# 7关系运算符:`<`、`<=`、`>=`、`>`、`instanceof`
# 8等价运算符:`==`、`!=`
# 9按位与:`&`
# 10按位异或:`^`
# 11按位或:`|`
# 12条件与:`&&`
# 13条件或:`||`
# 14三元运算符:`? :`
# 15赋值运算符:`=`、`+=`、`-=`、`*=`、`/=`、`%=`
# 16位赋值运算符:`&=`、`|=`、`<<=`、`>>=`、`>>>=`
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

注:不要过多的依赖运算的优先级来控制表达式的执行顺序,这样可读性太差,尽量使用()来控制表达式的执行顺序。不要把一个表达式写得过于复杂,如果一个表达式过于复杂,则把它分成几步来完成。

# 流程控制

# 顺序结构

顺序结构就是程序从上到下逐行地执行,表达式语句都是顺序执行的,并且上一行对某个变量的修改对下一行会产生影响。

# 分支语句

# if-else

格式:

if (条件表达式1) { //条件表达式必须是布尔表达式或布尔变量
  	语句块1;
} else if (条件表达式2) {
  	语句块2;
}
...
}else if (条件表达式n) {
 	语句块n;
} else {
  	语句块n+1;
}
1
2
3
4
5
6
7
8
9
10
11

执行流程:

if...else嵌套:在if的语句块中或在else语句块中,又包含了另一个条件判断,这样就构成了嵌套结构。当语句块中只有一条执行语句时一对{}可以省略,但建议保留。

# switch-case

格式:

switch(表达式){
    case 常量值1:
        语句块1;
        //break;
    case 常量值2:
        语句块2;
        //break; 
    // ...
   [default:
        语句块n+1;
        break;
   ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13

执行流程:

  • switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0)
  • case子句中的值必须是常量,不能是变量名或不确定的表达式值或范围
  • 同一个switch语句,所有case子句中的常量值互不相同
  • break语句用来在执行完一个case分支后使程序跳出switch语句块,如果没有break,程序会顺序执行到switch结尾
  • default子句是可选的,同时位置也是灵活的,当没有匹配的case时执行default语句

注:在switch语句中,如果case的后面不写break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个case的值,直接向后运行,直到遇到break或者整个switch语句结束。

# 比较

结论:凡是使用switch-case的结构都可以转换为if-else结构,反之不成立。

经验:如果既可以使用switch-case,又可以使用if-else,建议使用switch-case,效率稍高。

# 循环语句

# for循环

格式:

for (①初始化部分; ②循环条件部分; ④迭代部分){
         	③循环体部分;
}
1
2
3

执行流程:

注:

  • for(;;)中的两个;不能多也不能少
  • 初始化部分可以声明多个变量,但必须是同一个类型,用逗号分隔
  • 循环条件部分为boolean类型表达式,当值为false时,退出循环
  • 可以有多个变量更新,用逗号分隔

举例: 打印1-100之间所有是7的倍数的整数的个数及总和(体会设置计数器的思想):

public class ForTest2 {
    public static void main(String[] args) {
        int sum = 0; //记录总和
        int count = 0; //记录个数
        for (int i = 1; i < 100; i++) {
            if(i % 7 == 0){
                sum += i;
                count++;
            }
        }
        System.out.println("1-100之间所有是7的倍数的整数的和为:" + sum);
        System.out.println("1-100之间所有是7的倍数的整数的个数为:" + count);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# while循环

格式:

①初始化部分
while(②循环条件部分){
    ③循环体部分;
    ④迭代部分;
}
1
2
3
4
5

执行流程:

注:

  • while(循环条件)中循环条件必须是boolean类型
  • 注意不要忘记声明4迭代部分,否则循环将不能结束变成死循环
  • for循环和while循环可以相互转换,二者没有性能上的差别。实际开发中,根据具体结构的情况,选择哪个格式更合适
  • for循环与while循环的区别:初始化条件部分的作用域不同

举例: 从键盘输入整数,统计输入的正数、负数的个数,最后输入0结束:

import java.util.Scanner;

public class TestWhile {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        int positive = 0; //记录正数的个数
        int negative = 0; //记录负数的个数
        int num = 1; //初始化为特殊值,使得第一次循环条件成立
        while(num != 0){
            System.out.print("请输入整数(0表示结束):");
            num = input.nextInt();
            if(num > 0){
                positive++;
            }else if(num < 0){
                negative++;
            }
        }
        System.out.println("正数个数:" + positive);
        System.out.println("负数个数:" + negative);
        input.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# do-while循环

格式:

①初始化部分;
do{
	③循环体部分
	④迭代部分
}while(②循环条件部分); 
1
2
3
4
5

执行流程:

注:

  • 结尾while(循环条件)中循环条件必须是boolean类型
  • do{}while();最后有一个分号
  • do-while结构的循环体语句是至少会执行一次,这个和for和while是不一样的
  • 循环的三个结构for、while、do-while三者是可以相互转换的

举例: 随机生成一个100以内的数,猜这个随机数是多少:

import java.util.Scanner;

public class DoWhileTest {
    public static void main(String[] args) {
        //随机生成一个100以内的整数
        int num = (int)(Math.random()* 100);
        //声明一个变量,用来存储猜的次数
        int count = 0;
        Scanner input = new Scanner(System.in);
        int guess; //提升作用域
        do{
            System.out.print("请输入100以内的整数:");
            guess = input.nextInt();
            //输入一次,就表示猜了一次
            count++;
            if(guess > num){
                System.out.println("大了");
            }else if(guess < num){
                System.out.println("小了");
            }
        }while(num != guess);
        System.out.println("一共猜了:" + count+"次");
        input.close();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 嵌套循环

嵌套循环是指一个循环结构A的循环体是另一个循环结构B,比如for循环里面还有一个for循环,就是嵌套循环。其中for ,while ,do-while均可以作为外层循环或内层循环。

设外层循环次数为m次,内层为n次,则内层循环体实际上需要执行m*n次。

技巧:从二维图形的角度看,外层循环控制行数,内层循环控制列数。

经验:实际开发中,我们最多见到的嵌套循环是两层,一般不会出现超过三层的嵌套循环。如果将要出现,一定要停下来重新梳理业务逻辑,重新思考算法的实现,控制在三层以内,否则可读性会很差。

# break和continue的使用

关键字 适用范围 在循环结构中使用的作用 相同点
break switch-case循环结构 一旦执行就结束当前循环结构 此关键字的后面不能声明语句
continue 循环结构 一旦执行就结束当次循环结构 此关键字的后面不能声明语句

此外,很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它,但使程序容易出错,Java中的break和continue是不同于goto的。

最后,今天的内容就到这里,Java教程持续更新中,喜欢的话点个关注吧,下篇见!

🎁 公众号

小伙伴们大家好,上方扫码关注公众号「大数据技术开发」,与你分享我的成长历程与技术感悟~

Java之变量与基本数据类型
Java数组详解

← Java之变量与基本数据类型 Java数组详解→

最近更新
01
知识体系总览
02-27
02
读书笔记
02-21
03
深度学习
02-20
更多文章>
Theme by Vdoing | Copyright © 2019-2023 码农高飞 | 豫ICP备2021025399号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式