1 运算符
1.1 运算符概述
1.1.1 运算符概述
运算符是一种告诉计算机执行特定的数学或逻辑等操作的符号。Java运算符号包括:数学运算符、关系运算符、逻辑运算符、赋值运算符号、字符串连接运算符。计算机本质上只能处理数字,处理数字的最常见的方式就是使用运算符,如:a+b。
Java从C语言继承的丰富的运算符:
1.1.2 运算符要点
按照参与运算的元素个数来划分,运算符分为:
- 单目(元)运算符:比如 a++
- 双目(元)运算符:比如 a+b
- 三目(元)运算符:比如 running ? a : b
不同的运算符具有不同的优先级,多个运算符组成复杂运算时,优先级高的运算符先行计算。在优先级顺序里,括号级别最高,其次是单目运算、双目运算(先乘除后加减)、三目运算,赋值运算符的优先级最低。
运算符优先级相同时,按照结合性顺序计算。 大多数运算符的结合性是从左向右,但是单目运算符、赋值运算符和三目运算符的结合性是从右向左。
由于运算符种类繁多,完全靠优先级和结合性来确定运算顺序,会导致代码难以阅读,可维护性降低。因此,实际编码时,建议利用()调整优先级顺序,按照便于理解的顺序添加括号,从而提高代码的可阅读性和可维护度。
1.1.3【案例】运算符示例
新建类,类名为 OperatorDemo,添加代码测试运算符的使用。
案例示意代码如下:
package day02;
public class OperatorDemo {
public static void main(String[] args) {
//优先级
int c = 4 + 6 / 2 + 8 * 2;
System.out.println(c);
//结合性
int n = 3 + 4 + 5 + 6;
System.out.println(n);
//利用()调整计算顺序
int k = 1024 * (100 + 2);
System.out.println(k);
}
}
1.2 算术运算符
1.2.1 算术四则运算
四则运算是最常见的数学运算,运算规则与数学中的数学运算基本一样,但是也有一些细微区别。一样的规则这里就不再复述,这里主要讨论一些不同之处:
- 相同数据类型参与数学运算,得到相同类型的结果
- 整数除法得到整数结果
- 参与数学运算的数据类型不一致时候,就近自动数据类型转换,转换为相同类型再进行计算
- byte、short、char按照int类型计算
- 计算结果超过数据类型范围会溢出
- 为了提高运行期间的性能,常量计算会在编译期间优先计算
1.2.2【案例】算术四则运算示例
在day02包下新建类,类名为 ArithmeticDemo,测试四则运算:
- 实现两个int类型变量的加法运算
- 验证并解决溢出问题
- 实现两个整型变量的除法运算
- 验证运算过程中的自动类型转换
案例示意代码如下:
package day02;
public class ArithmeticDemo {
public static void main(String[] args) {
//一般情况
int a = 50;
int b = 100;
int c = a + b; //整数加整数得到整数
System.out.println(c);
//溢出问题
a = Integer.MAX_VALUE;
b = 8;
c = a + b;//溢出时候不会报任何错误!!
System.out.println(c);
//溢出会隐含发生
a = Integer.MAX_VALUE;
b = 5;
//整数a加上整数b得到溢出的整数结果,再将整数赋值给l
long l = a + b;
System.out.println(l);
//解决溢出问题:
l = (long)a + b;
System.out.println(l);
//整除情况
a = 9;
b = 2;
c = 9/2; //整除得到4
System.out.println(c)
;
//浮点除法
double dx = 9.0/2;
System.out.println(dx);
//自动转换类型
a = 5;
l = 100;
long n = a + l; // Java先将a转换为long类型数据再与l相加
System.out.println(n);
// byte short char 按照int计算得到int结果
byte b1 = 5;
short s1 = 6;
// short s2 = b1 + s1; // 编译错误,byte、short按照int计算得到int类型结果
int n1 = b1 + s1;
System.out.println(n1);
//常量编译期间优化
// 3是int常量,100是int,编译器运算为103不超过byte范围可以赋值
byte b2 = 3 + 100;
// byte b3 = 100 + 100; // 编译错误,100与100的和超过byte范围
System.out.println(b2);
// System.out.println(b3);
}
}
1.2.3 取余数运算
取余数计算,即获得除法计算的余数。在日常生活中,余数计算不常用;但是在计算机编程中,余数计算经常被用到。下面就讨论一下余数计算的特点,正是因为这些特点,余数计算才经常被使用。
在数学计算中,数学除法规则如下:
在java代码中,余数计算规则如下:
当除数是正数时,余数运算规律为:
- 被除数是正数时,余数是介于0到除数之间的整数,如:除数3,则余数是0 1 2之一, 范围是[0,3)
- 如果被除数分别是0 1 2 3 4 ... ,则余数现实为周期性数值,如:除数3则余数分别是0 1 2 0 1 2 0 1 2 ...
- 如果被除数是负数,除数是3其余数范围是:(-3, 0]
在java开发中,余数计算常用于:
- 控制计算结果的范围,比如控制计算结果是3以内的数,就对3取余数就行了
- 控制周期性运算:比如“发牌”,周期循环动画
1.2.4【案例】取余运算示例
在day02包下新建类,类名为 RemainderDemo,测试取余运算。
案例示意代码如下:
package day02;
public class RemainderDemo {
public static void main(String[] args) {
System.out.println(-5%3);
System.out.println(0%3);
System.out.println(1%3);
System.out.println(2%3);
System.out.println(3%3);
System.out.println(4%3);
System.out.println(5%3);
System.out.println(6%3);
System.out.println(7%3);
}
}
1.2.5 自增/自减运算
自增、自减运算就是将当前变量的值增加1或者减少1。传统数学计算中是不存在自增或者自减运算的,由于软件开发中经常需要按照次序连续处理数据,计算机专家们按照自己的使用习惯设计了自增自减运算。这些运算经常用于在开发编码中,可以使程序编码变的非常干练简洁。自增运算 ++ 和自减运算符—都是单目运算符,即只有一个操作元素参与运算,其基本运算规则是将参与运算的数值增加或者减少1。
查看如下图所示的运算示意:
自增/自减一共分为 4 种写法:
1、i++ 称为“后加加”
- 先取变量i的值作为 i++ 整体表达式的值,再将i的值增加1
- 假设运算前i=1,则运算后 i++ 的结果为1 ,i为2
2、++i 称为“先加加”
- 先将i的值增加1,再取变量i的值作为 ++i 整体表达式的值
- 假设运算前i=1,则运算后 ++i 的结果为2 ,i为2
3、i-- 称为“后减减”
- 先取变量i的值作为 i-- 整体表达式的值,再将i的值减少1
- 假设运算前i=1,则运算后 i—的结果为1 ,i为0
4、--i 称为“先减减”
- 先将i的值减少1,再取变量i的值作为 --i 整体表达式的值
- 假设运算前i=1,则运算后 --i 的结果为0 ,i为0
1.2.6【案例】自增/自减运算示例
在day02包下新建类,类名为 IncrementDemo,测试自增和自减运算。
案例示意代码如下:
package day02;
public class IncrementDemo {
public static void main(String[] args) {
int i = 1;
System.out.println(i++); //1
System.out.println(i); //2
i = 1;
System.out.println(++i); //2
System.out.println(i); //2
i = 1;
System.out.println(i--); //1
System.out.println(i); //0
i = 1;
System.out.println(--i); //0
System.out.println(i); //0
}
}
1.3 关系运算符
1.3.1 关系运算符
关系运算用于比较数值的大、小、相等关系,Java关系运算符与数学上的关系运算规则类似。在开发中用来判断数据的大小以及是否相等。
Java的关系运算符如下所示:
关系运算的结果是boolean类型数据:如果比较结果成立则得到true,否则得到false。规则如下所示:
1.3.2【案例】关系运算符示例
在day02包下新建类,类名为 RelationalDemo,测试关系运算。
案例示意代码如下:
package day02;
public class RelationalDemo {
public static void main(String[] args) {
int age = 5;
System.out.println(age>12);
System.out.println(age>=12);
System.out.println(age<12);
System.out.println(age<=12);
System.out.println(age==5);
System.out.println(age!=5);
}
}
1.4 逻辑运算符
1.4.1 什么是逻辑运算
利用逻辑运算可以将简单的逻辑复合成为复杂逻辑,实现复杂判断。在软件开发过程中,如果遇到复杂的逻辑条件判断,就可以利用逻辑运算符将简单逻辑组合为复杂逻辑。
比如,判定一个人是否为老头的逻辑为:年龄大于60的男性。则为两个逻辑判断组合而成:年龄大于60,且,性别为男。
1.4.2 逻辑运算符
参与逻辑运算的变量或表达式都是boolean类型,运算结果也为boolean类型。
逻辑运算符有3种:
- 逻辑与 &&
- 逻辑或 ||
- 逻辑非 !
三种逻辑运算符的运算规则如下:
1.4.3【案例】闰年判断
闰年是比普通年份多出一段时间的年份,目的是为了弥补人为规定的纪年与地球公转产生的差异。地球公转一年的周期称为回归年,总时长为 365天5时48分46秒 ,也是太阳直射点来回的周期,也就是通常说的一年。
按照一年365天计算,则存在时间上的差异,因为设计出来闰年以实现时间上的找平补齐。
目前使用的格里高利历闰年规则如下:
- 公元年份除以4可整除但除以100不可整除,为闰年
- 公元年份除以400可整除,为闰年
可以简单总结为:四年一闰,百年不润,四百年再闰。
在day02包下新建类,类名为LogicalDemo1,编写代码:输入年份数字,判断是否为闰年并输出结果。
案例示意代码如下:
package day02;
import java.util.Scanner;
public class LogicalDemo1 {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("输入年份:");
int year = console.nextInt();
boolean b=
((year % 4 == 0) && !(year % 100 == 0))||(year % 400 == 0);
System.out.println(b);
}
}
注意:这里使用了Scanner,它是Java提供的API,利用Scanner可以从控制台获取用户输入的参数,使用步骤如下:
- 导入Scanner API: import java.util.Scanner;
- 创建Scanner对象:Scanner console = new Scanner(System.in);
- 调用方法获取用户输入信息:int year = console.nextInt();
1.4.4 短路逻辑运算
短路逻辑运算是指在进行两元逻辑运算时,如果能够通过第一个表达式得到整体运算结果,就不再运算第二个表达式。
Java的两元逻辑运算符 && 和 || 都按照短路规则执行。短路运算规则有着诸多的好处,首先可以减少运算次数提高程序性能,还可以利用第一个表达式运算结果跳过第二个表达式,避免第二个表达式的运算错误(这个现象会在面向对象阶段详细阐述)。
短路&&运算的规则如下所示:
1.4.5【案例】短路逻辑运算示例
在day02包下新建类,类名为 LogicalDemo2,测试短路逻辑运算。
案例示意代码如下:
package day02;
public class LogicalDemo2 {
public static void main(String[] args) {
char gender = '女';
int age = 26;
boolean pass = gender == '女' || age >= 60;
System.out.println(pass);
}
}
由于短路逻辑更接近生活逻辑,并且可以一定程度的提高计算速度,所以短路逻辑还是比较常用的。
1.5 赋值运算符
1.5.1 赋值运算
基本的赋值运算符是“=”,你一开始可能会以为它是“等于”,其实并非如此。它实际上意味着把右边表达式的值赋给左侧变量。
由于赋值运算是优先级别最低的运算符,在其他运算之后进行运算,所以在Java中使用如下运算是可以的:
int i = 9;
i = i + 10;
System.out.println(i); //19
赋值运算本身也是一个“赋值表达式”,运算结束后整个“赋值表达式”有值,其值是最后赋值的值,如:
int n = 9;
int k;
System.out.println(k = n+5); //14
1.5.2【案例】赋值运算示例
在day02包下新建类,类名为 AssignmentDemo2,测试赋值运算。
案例示意代码如下:
package day02;
public class AssignmentDemo2 {
public static void main(String[] args) {
int a, b, c, d;
a = b = c = d = 20;
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
由上述代码可以看出:赋值运算的结合性是从右到左,与常规的数学运算习惯的从左到右不同。
1.5.3 复合赋值运算
“=”和双目运算符组合为复合赋值运算:可以看成是双目运算和赋值运算的简化写法。利用复合赋值运算可以简化代码的编写,提高编程效率。如下图所示:
常见复合赋值运算有:
1.5.4 【案例】复合赋值运算示例
在day02包下新建类,类名为 AssignmentDemo3,测试复合赋值运算。
案例示意代码如下:
public class AssignmentDemo3 {
public static void main(String[] args) {
int n = 1;
n += 5; // n = (int)(n+5) //n=6
System.out.println(n);
n = 1;
n -= 8; // n = (int)(n-8)
System.out.println(n);// -7
n = 1;
n +=9.6; // n = (int)(n+9.6)
System.out.println(n); // 10
}
}
1.6 字符串连接运算符
1.6.1 字符串连接运算
字符串连接运算就是将两个字符串连接为一个新的字符串。因为字符串是Java最常用显示信息方式,所以字符串连接也是最常见的字符串运算。
Java字符串连接使用“+”实现:“+”运算除了可以用于数学加法还可以连接字符串。也就是是说一个加号“+”具有两种功能,这种一个运算符号两种功能现象称为:“运算符重载”。
1.6.2 “+”运算符规则
使用“+”元素时:
- 如果加号两侧都是数值就是数值加法
- 如果加号的一侧出现了字符串,就按照字符串连接运算计算
- 字符串连接时候,会将不是字符串的数据转换为字符串再进行连接
规则如下所示:
代码示意如下:
System.out.println(5+5.5);
System.out.println(5+"5.5");
System.out.println(5+5+"5.5");
System.out.println("5"+5+"5.5");
1.7 三元运算符
1.7.1 三元运算符
三元/目运算符也称为“条件运算符”或者“条件表达式”,其本质上是一种简化版的条件判断语句。因为其简洁方便在开发中经常被使用。其逻辑规则如下所示:
可以看出,在计算三元运算符时:
- 先计算“boolean表达式”
- 如果“boolean表达式”的值为true,整个表达式的值为“表达式1”的值
- 如果“boolean表达式”的值为false,整个表达式的值为“表达式2”的值
1.7.2【案例】三元运算符示例
在day02包下新建类,类名为 TernaryDemo,测试三元运算符。
案例示意代码如下:
package day02;
import java.util.Scanner;
public class TernaryDemo {
public static void main(String[] args) {
// 挑选a和b中的最大值
Scanner console = new Scanner(System.in);
System.out.print("输入a b:");
int a = console.nextInt();
int b = console.nextInt();
int max = a > b ? a : b;
System.out.println(max);
}
}
2 分支流程控制
2.1 流程控制概述
2.1.1 流程控制概述
流程控制是指在程序运行时,控制指令运行的顺序。流程控制通过流程控制语句实现,利用流程控制语句可以控制程序的执行流程、控制算法的执行顺序。
流程控制可以分为3类:
其中:
- 顺序:程序按照从上到下顺次执行指令序列
- 分支:根据分支条件选择一路指令序列执行
- 循环:根据循环条件反复执行指令序列
2.2 分支流程控制—if语句
2.2.1 分支流程控制概述
分支是指,根据分支条件选择一路指令序列执行。使用分支流程控制语句,可以根据条件控制程序的执行。比如:可以处理碰到边缘就出现反弹动作;价格超过一定值就打折扣等。分支条件语句在软件编码中,是很常用的。
Java的分支条件语句有:
- if 语句
- switch 语句
分支控制分为3种:
2.2.2 if单路分支流程控制
if语句用于处理单路分支流程控制。其语法结构如下:
上述语句的执行流程为:
1、先执行指令1
2、然后执行判断分支条件表达式,得到boolean值
- 若值为true,则执行if语句块中的指令2
- 若值为false,则不执行if语句块中的指令2
3、最后执行指令3
利用单路分支控制语句可以处理分支逻辑操作,比如: 当商品总价大于等于500,则打8折。示意如下:
使用分支流程控制语句时候,要先分析业务处理流程,如果业务流程能够套用分支流程控制,就将业务流程套用到分支流程控制语句中,就可以解决业务问题了。
2.2.3 【案例】if 单路分支示例
在day02包下新建类,类名为IfDemo1,要求实现:
- 输入商品总价
- 如果总价不小于500,则打八折
- 输出付款金额
案例示意代码如下:
package day02;
import java.util.Scanner;
public class IfDemo1 {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("输入商品总价:");
double total = console.nextDouble();
if(total>=500) {
//total = total * 0.8;
total *= 0.8;
}
System.out.println("付款金额:"+total);
}
}
2.2.4 if else双路分支语句
if 与else 搭配可以实现双路分支语句,其语法如下:
其执行流程为:
1、执行指令1
2、判断if分支条件表达式的值:
- 若值为true,则执行指令2
- 若值为false,则执行指令3
3、执行指令4
这就是二选一的执行流程,可以用于解决如下案例:如果商品总价大于等于500,则打8折,如果小于500打95折。
分析如下所示:
2.2.5【案例】if else 双路分支示例
在day02包下新建类,类名为IfDemo2,要求实现:
- 输入商品总价
- 如果总价不小于500,则打八折;否则打九折
- 输出付款金额
案例示意代码如下:
package day02;
import java.util.Scanner;
public class IfDemo2 {
public static void main(String[] args) {
/**
* if esle Demo
*/
Scanner console = new Scanner(System.in);
System.out.print("请输入总价:");
double total = console.nextDouble();
if(total>=500) {
total *= 0.8;
}else {
total *= 0.95;
}
System.out.println("应付款项:"+total);
}
}
2.2.6 if else if 多路分支语句
if else 可以组合成多路分支语句,用来实现根据多个条件多选一执行,比如分段打折问题:
- 如果商品总价大于等于800,则打7折
- 如果商品总价小于800大于等于500,则打8折
- 如果商品总价小于500大于等于200,则打9折
- 如果商品总价小于200,则打95折
其流程可以描述如下:
利用if else if 语句就可以解决这个问题:
2.2.7【案例】if else if 多路分支示例
在day02包下新建类,类名为IfDemo3,要求实现:
- 输入商品总价
- 根据不同价位进行折扣计算
- 输出付款金额
案例示意代码如下:
package day02;
import java.util.Scanner;
public class IfDemo3 {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("输入总金额:");
double total = console.nextDouble();
if(total>=800) {
total *= 0.7;
}else if(total>=500) {
total *= 0.8;
}else if(total>=200) {
total *= 0.9;
}else {
total *= 0.95;
}
System.out.println("应付款:"+total);
}
}
2.3 分支流程控制—switch语句
2.3.1 switch case 语句
switch ... case 是Java的一种多路分支语句,可以根据整数、字符串、枚举类型进行分支:从不同的程序入口开始执行。
具体语法如下:
- Java 5 开始switch case语句支持枚举类型
- Java 7 开始switch case开始支持支持String类型
- break 用于结束switch语句
- byte、short、char可以自动转换为int,可以作为分支条件
- case 后只能是常量,不能是表达式
具体使用规则如下所示:
if else if 语句已经可以实现多路分支了,而switch case语句在整数等情况下进行分支判断时候性能更好。所以根据整数值进行分支时候建议使用switch case,这样可以提升运算性能。
注意:if else if是万能多路分支语句,而switch只能对整数(字符串、枚举)进行分支,是限定整数情况下才能使用;而使用switch case的根本原因就是因为其性能优势。所以在开发中,如果可以根据整数进行分支,建议使用switch case。
2.3.2【案例】switch case分支示例
在day02包下新建类,类名为SwitchDemo,要求实现:
- 根据学生的成绩输出学生的等级(输入的成绩是百分制)
- 输出评定等级:100~90分输出A,89~80输出B,79~60输出C,59以下输出D
分析这个案例,其代码逻辑如下所示:
对于相同的case语句,可以去除break后合并case语句,简化代码:
案例示意代码如下:
package day02;
import java.util.Scanner;
public class SwitchDemo {
public static void main(String[] args) {
Scanner console = new Scanner(System.in);
System.out.print("输入分数:");
int score = console.nextInt();
switch(score/10) {
case 10:
case 9:
System.out.println("A");
break;
case 8:
System.out.println("B");
break;
case 7:
case 6:
System.out.println("C");
break;
default:
System.out.println("D");
}
}
}
2.4 Java新特性-switch表达式
2.4.1 什么是switch表达式
Java 12引入了一种新的switch表达式,它在语法和功能上有所改进,使得编写更简洁、易读的代码成为可能。
传统的switch语句中,每个case后面需要使用break语句来结束,而Java 12的switch表达式中,可以使用"->"箭头来表示代码块的执行,并且不需要显式使用break语句。此外,Java 12的switch表达式还支持新的语法特性,如匹配模式(Pattern Matching)、Lambda表达式和块标签。
下面是Java 12 switch表达式的基本语法:
int result = switch (expression) {
case value1 -> {
// 执行代码块1
yield result1;
}
case value2 -> {
// 执行代码块2
yield result2;
}
// 更多的case语句
default -> {
// 执行默认代码块
yield defaultResult;
}
};
在这个语法中,switch表达式的结果被赋值给一个变量(此例中的result)。每个case后面的箭头(->)表示对应的代码块的执行,并且可以使用yield语句来返回一个值作为表达式的结果。如果case中只有一个表达式作为返回值的时候可以省略{}和yield。
2.4.2【案例】使用switch表达式计算价格
在Java 12中,我们可以使用箭头操作符(->)来指定每个分支的结果。
String fruit = "apple";
int quantity = 2;
double totalPrice = switch (fruit) {
case "apple" -> 1.0 * quantity;
case "banana" -> 0.8 * quantity;
case "orange" -> 0.5 * quantity;
default -> 0 * quantity;
};
System.out.println("Total price: $" + totalPrice);
在这个例子中,我们根据不同的水果类型计算总价格。使用switch表达式,我们可以直接在分支条件中进行计算,并返回结果。
Java 12的switch表达式提供了更简洁、灵活的语法,使得处理多个分支情况的代码更加清晰易读。它在简化代码、提高开发效率方面有很大的帮助。