Day3-第2章 Java基础语法(续)
2.10.7 位运算符
| 位运算符 | 符号解释 | |
|---|---|---|
& | 按位与,当两位相同时为1时才返回1 | |
| ` | ` | 按位或,只要有一位为1即可返回1 |
~ | 按位非,将操作数的每个位(包括符号位)全部取反 | |
^ | 按位异或。当两位相同时返回0,不同时返回1 | |
<< | 左移运算符 | |
>> | 右移运算符 | |
>>> | 无符号右移运算符 |
注意:
- 位运算符计算时都是基于==二进制补码==进行运算的,但是看结果时需要换成==二进制原码==再换成十进制看结果。从二进制到十进制都是基于补码,正数的原码反码补码都一样,负数原码反码补码不一样
- 按位与&、按位或|、按位异或^ 两边操作数必须类型相同才能计算,其中byte,short,char在计算时自动按照int类型处理
- 左移<<、右移>>、无符号右移>>> 需要移n位,当n超过该数据类型的总位数时,相当于左移(n-总位数)位
(1)左移:<<
实际运算规则:左移几位,即左边高位丢弃几位,右边低位补几个0。
快速运算口诀:除符号位从0变1或1变0外,左移几位就相当于乘以2的几次方。
3<<4 类似于 3*2的4次= 3*16 = 48
-3<<4 类似于 -3*2的4次= -3*16 = -48
(2)右移:>>
实际运算规则:右移几位,即右边低位丢弃几位,左边原符号位是0就补0是1就补1。所以右移不会出现正数变负数,负数变正数的情况。
快速运算口诀:类似于除以2的n次,如果不能整除,向下取整
69>>4 类似于 69/2的4次 = 69/16 =4
-69>>4 类似于 -69/2的4次 = -69/16 = -5
(3)无符号右移:>>>
实际运算规则:右移几位,即右边低位丢弃几位,左边直接补几个0。
正数:和右移一样
负数:右边移出去几位,左边补几个0,结果变为正数。
69>>>4 类似于 69/2的4次 = 69/16 =4
-69>>>4 结果:268435451
(4)按位与:&
运算规则:对应位都是1才为1。
1 & 1 结果为1
1 & 0 结果为0
0 & 1 结果为0
0 & 0 结果为0
9&7 = 1
-9&7 = 7
(5)按位或:|
运算规则:对应位只要有1即为1。
1 | 1 结果为1
1 | 0 结果为1
0 | 1 结果为1
0 & 0 结果为0
9|7 结果: 15
-9|7 结果: -9
(6)按位异或:^
运算规则:对应位一个为1一个为0,才为1
1 ^ 1 结果为0
1 ^ 0 结果为1
0 ^ 1 结果为1
0 ^ 0 结果为0
9^7 结果为14
-9^7 结果为-16
(7)按位取反:~
运算规则:~0就是1
~1就是0
~9 结果:-10
~-9 结果:8
(8)程序员模式计算器(选讲)
| 项目 | 说明 | |
|---|---|---|
| BYTE | 1个字节 | |
| WORD | 2个字节 | |
| DWORD | 4个字节 | |
| QWORD | 8个字节 | |
| AND | 按位与 & | |
| OR | 按位或 | |
| NOT | 按位取反 ~ | |
| XOR | 按位异或 ^ | |
| <<(算术移位) | 左移 << | |
| >>(算术移位) | 右移 >> | |
| >>(逻辑移位) | 无符号右移 >>> |
2.10.8 赋值运算符(下)
| 运算符 | 符号解释 | |
|---|---|---|
| = | 将右边的常量值/变量值/表达式的值,赋值给左边的变量 | |
| += | 将左边变量的值和右边的常量值/变量值/表达式的值进行相加,最后将结果赋值给左边的变量 | |
| -= | 将左边变量的值和右边的常量值/变量值/表达式的值进行相减,最后将结果赋值给左边的变量 | |
| *= | 将左边变量的值和右边的常量值/变量值/表达式的值进行相乘,最后将结果赋值给左边的变量 | |
| /= | 将左边变量的值和右边的常量值/变量值/表达式的值进行相除,最后将结果赋值给左边的变量 | |
| %= | 将左边变量的值和右边的常量值/变量值/表达式的值进行相模,最后将结果赋值给左边的变量 | |
| <<= | 将左边变量的值左移右边常量/变量值/表达式的值的相应位,最后将结果赋值给左边的变量 | |
| >>= | 将左边变量的值右移右边常量/变量值/表达式的值的相应位,最后将结果赋值给左边的变量 | |
| >>>= | 将左边变量的值无符号右移右边常量/变量值/表达式的值的相应位,最后将结果赋值给左边的变量 | |
| &= | 将左边变量的值和右边的常量值/变量值/表达式的值进行按位与,最后将结果赋值给左边的变量 | |
| = | 将左边变量的值和右边的常量值/变量值/表达式的值进行按位或,最后将结果赋值给左边的变量 | |
| ^= | 将左边变量的值和右边的常量值/变量值/表达式的值进行按位异或,最后将结果赋值给左边的变量 |
public class OperatorDemo04 {
public static void main(String[] args) {
int a = 3;
int b = 4;
int c = a + b;
b += a;// 相当于 b = b + a ;
System.out.println(a); // 3
System.out.println(b); // 7
System.out.println(c); //7
short s = 3;
// s = s + 4; 代码编译报错,因为将int类型的结果赋值给short类型的变量s时,可能损失精度
s += 4; // 代码没有报错
//因为在得到int类型的结果后,JVM自动完成一步强制类型转换,将int类型强转成short
System.out.println(s);
int j = 1;
j += ++j * j++;//相当于 j = j + (++j * j++);
System.out.println(j);//5
int m = 1;
m <<= 2;
System.out.println(m);
}
}
运算规则和要求:
(1)=左边一定是一个变量,右边可以是常量、变量、表达式
(2)赋值运算一定是最后算的,优先级最低
(3)如果是=赋值运算符,那么=右边值的类型必须 “小于等于” 左边变量的类型
如果是+=,-=等组合赋值运算符,那么
要是最后计算计算结果值的类型 “小于等于” 左边变量的类型 时,正常赋值;
要是最后计算计算结果值的类型 “大于” 左边变量的类型时,会隐式的发生强制类型转换。
2.10.9 标点符号(Separators)
在Java8中一共有12个标点符号。(从一开始就需要开始留意代码中不同位置使用的不同标点符号,==训练眼力==)
- 小括号/圆括号()用于强制类型转换、表示优先运算表达式、方法参数列表
- 大括号/花括号{}用于数组元素列表、类体、方法体、复合语句代码块边界符
- 中括号/方括号[]用于数组
- 分号;用于结束语句
- 逗号,用于多个赋值表达式的分隔符和方法参数列表分隔符
- 英文句号.用于成员访问和包目录结构分隔符
- 英文省略号...用于可变参数
- @用于注解
- 双冒号::用于方法引用
各个标点符号的使用在后续章节中一一揭晓。
class Sign{
public static void main(String[] args){
int x,y,z;//声明了3个int类型的变量
int a = 1, b = 2, c = 1;//声明了3个int类型的变量,并且初始化
//int m = n = 1;//n没有声明
}
}
2.10.10 运算符优先级
| 优先级 | 符号 | 优先级 | 符号 | ||
|---|---|---|---|---|---|
| 1 | ( ) | 9 | == != | ||
| 2 | .(成员访问操作符,请看第5章面向对象上) [ ](数组元素访问符,请看第4章数组) | 10 | & | ||
| 3 | +(正) -(负) | 11 | |||
| 4 | ++ -- ~ ! | 12 | |||
| 5 | * / % | 13 | && | ||
| 6 | +(加:求和、拼接) -(减) | 14 | |||
| 7 | << >> >>> | 15 | ? : | ||
| 8 | < > <= >= instanceof(请看第6章面向对象中) | 16 | = += -= *= /= %= <<= >>= >>>= &= ^= | = |
口诀:
小括号( )优先算;成员老二正负三;单目运算排第四;
乘除余五加减六;移位七,关系八;等和不等排第九;
位与、异或和位或;短路与和短路或;依次从十到十四;
条件排在第十五;赋值一定是最后;不把握就加小括号( )。
虽然有口诀,但大部分人都记不全所有运算符的优先级。为了避免因为搞混运算符的优先级而编写运算次序不正确的表达式,建议读者尽量不要编写过于复杂的表达式,当表达式过于复杂时,可以拆分为多个步骤完成。
Day3-第3章 流程控制语句结构
所谓流程就是代码执行的步骤。用于控制代码执行顺序的语句结构称为流程控制语句结构。最基本的流程控制语句结构有:顺序结构、分支结构、循环结构。
3.1 顺序结构
方法(例如main方法)体中的语句按顺序依次执行,这种结构就称为顺序结构。
public class TestStatement{
public static void main(String[] args){
int x = 1;
int y = 2;
System.out.println("x = " + x);
System.out.println("y = " + y);
//对x、y的值进行修改
x++;
y = 2 * x + y;
x = x * 10;
System.out.println("x = " + x);
System.out.println("y = " + y);
}
}
3.2 输入输出语句
1 输出语句
-
换行输出语句:输出内容后进行换行,格式如下:
System.out.println(输出内容);//输出内容之后,紧接着换行 System.out.println();//只换行
-
不换行输出语句:输出内容后不换行,格式如下
System.out.print(输出内容);//输出内容之后不换行 System.out.print('\n'); System.out.print("\n"); System.out.print(); //编译报错
public class TestPrintlnAndPrint {
public static void main(String[] args) {
String name = "柴林燕";
int age = 18;
//对比如下两组代码:
System.out.println(name);
System.out.println(age);
System.out.print(name);
System.out.print(age);
System.out.println(); //()里面为空,效果等同于换行,输出一个换行符
//等价于 System.out.print("\n"); 或 System.out.print('\n');
//System.out.print();//错误,()里面不能为空 核心类库PrintStream类中没有提供print()这样的方法
//对比如下两组代码:
System.out.print("姓名:" + name +",");//""中的内容会原样显示,如果()中有多项内容,那么必须使用 + 连接起来
System.out.println("年龄:" + age);
System.out.print("name = " + name + ",");
System.out.println("age = " + age);
}
}
2 输入语句
键盘输入代码的四个步骤:
1、申请资源,创建Scanner类型的对象
2、提示输入xx
3、接收输入内容
4、全部输入完成之后,释放资源,归还资源
1、各种类型的数据输入
示例代码:
import java.util.Scanner;
//如果在.java源文件上面没有这句import语句,
//那么在代码中每次使用Scanner就要用java.util.Scanner的全名称,比较麻烦
/*
键盘输入代码的四个步骤:
1、申请资源,创建Scanner类型的对象
2、提示输入xx
3、接收输入内容
4、全部输入完成之后,释放资源,归还资源
如果你在键盘输入过程中,遇到java.util.InputMismatchException异常,
说明你输入的数据,其类型与接收数据的变量的类型不匹配。
*/
public class Test05Input {
public static void main(String[] args) {
//1、准备Scanner类型的对象
//Scanner是一个引用数据类型,它的全名称是java.util.Scanner
//input就是一个引用数据类型的变量了,赋给它的值是一个对象(对象的概念我们后面学习,暂时先这么叫)
//new Scanner(System.in)是一个new表达式,该表达式的结果是一个对象
//引用数据类型 变量 = 对象;
//这个等式的意思可以理解为用一个引用数据类型的变量代表一个对象,所以这个变量的名称又称为对象名
//我们也把input变量叫做input对象
Scanner input = new Scanner(System.in);//System.in默认代表键盘输入
//这里变量名是input,下面就用input
//2、提示输入xx
System.out.print("请输入一个整数:");
//3、接收输入内容
int num = input.nextInt();
System.out.println("num = " + num);
//列出其他常用数据类型的输入
/*
long bigNum = input.nextLong();
double d = input.nextDouble();
boolean b = input.nextBoolean();
String s = input.next();
char c = input.next().charAt(0);//先按照字符串接收,然后再取字符串的第一个字符(下标为0)
*/
//释放资源
input.close();
}
}
2、next()与nextLine()
import java.util.Scanner;
/*
next()方法:
遇到空格等空白符,就认为输入结束
nextLine()方法:
遇到回车换行,才认为输入结束
*/
public class Test08NextAndNextLine {
public static void main(String[] args) {
//申请资源
Scanner input = new Scanner(System.in);
System.out.print("请输入姓名:");
//String name = input.next();//张 三 只能接收张,后面的空格和三无法接收,被下面的输入接收
String name = input.nextLine();
System.out.println("name = " + name);
System.out.print("请输入年龄:");
int age = input.nextInt(); //23回车换行 这里只接收23,回车换行被下面的输入接收
input.nextLine();//读取23后面的回车换行,但是这个不需要接收,只有下面一个输入是nextLine()情况下才需要这样,如果下面的输入是next()或者是nextInt(),nextDouble()等就不需要这么干
System.out.println("age = " + age);
System.out.print("请输入电话号码:");
String tel = input.nextLine();
System.out.println("tel = " + tel);
//释放资源
input.close();
}
}
3.3 分支语句
1 .单分支条件判断:if
- if语句第一种格式: if
if(条件表达式){
语句体;
}
-
执行流程
-
首先判断条件表达式看其结果是true还是false
-
如果是true就执行语句体
-
如果是false就不执行语句体
-
案例:在程序运行时由用户从键盘输入两个整数,然后以先小后大的顺序输出这两个整数。
import java.util.Scanner;
public class Test09If {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入第一个整数:");
int small = input.nextInt();
System.out.print("请输入第二个整数:");
int big = input.nextInt();
if (small > big) {
int temp = small;
small = big;
big = temp;
}
System.out.println("small=" + small + ",big=" + big);
input.close();
}
}
2 .双分支条件判断:if...else
- if语句第二种格式: if...else
if(关系表达式) {
语句体1;
}else {
语句体2;
}
-
执行流程
- 首先判断关系表达式看其结果是true还是false
- 如果是true就执行语句体1
- 如果是false就执行语句体2
() 案例:从键盘输入一个整数,判定是偶数还是奇数
import java.util.Scanner;
public class Test10IfElse {
public static void main(String[] args){
// 判断给定的数据是奇数还是偶数
Scanner input = new Scanner(System.in);
System.out.print("请输入整数:");
int a = input.nextInt();
if(a % 2 == 0) {
System.out.println(a + "是偶数");
} else{
System.out.println(a + "是奇数");
}
input.close();
}
}
3. 多分支条件判断:if...else if
- if语句第三种格式: if...else if ...else
if (判断条件1) {
执行语句1;
} else if (判断条件2) {
执行语句2;
}
...
}else if (判断条件n) {
执行语句n;
} else {
执行语句n+1;
}
-
执行流程
-
首先判断关系表达式1看其结果是true还是false
-
如果是true就执行语句体1,然后结束当前多分支
-
如果是false就继续判断关系表达式2看其结果是true还是false
-
如果是true就执行语句体2,然后结束当前多分支
-
如果是false就继续判断关系表达式…看其结果是true还是false
-
…
-
如果没有任何关系表达式为true,就执行语句体n+1,然后结束当前多分支。
-
案例:通过指定考试成绩,判断学生等级,成绩范围[0,100]
- 90-100 优秀
- 80-89 好
- 70-79 良
- 60-69 及格
- 60以下 不及格
import java.util.Scanner;
public class Test11IfElseIf {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入成绩[0,100]:");
int score = input.nextInt();
if(score<0 || score>100){
System.out.println("你的成绩是错误的");
}else if(score>=90 && score<=100){
System.out.println("你的成绩属于优秀");
}else if(score>=80 && score<90){
System.out.println("你的成绩属于好");
}else if(score>=70 && score<80){
System.out.println("你的成绩属于良");
}else if(score>=60 && score<70){
System.out.println("你的成绩属于及格");
}else {
System.out.println("你的成绩属于不及格");
}
input.close();
}
}
import java.util.Scanner;
public class Test11IfElseIf {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入成绩[0,100]:");
int score = input.nextInt();
if(score<0 || score>100){
System.out.println("你的成绩是错误的");
}else if(score>=90){
System.out.println("你的成绩属于优秀");
}else if(score>=80){
System.out.println("你的成绩属于好");
}else if(score>=70){
System.out.println("你的成绩属于良");
}else if(score>=60){
System.out.println("你的成绩属于及格");
}else {
System.out.println("你的成绩属于不及格");
}
input.close();
}
}
4. if..else嵌套
在if的语句块中,或者是在else语句块中, 又包含了另外一个条件判断(可以是单分支、双分支、多分支)
执行的特点: (1)如果是嵌套在if语句块中的 只有当外部的if条件满足,才会去判断内部的条件 (2)如果是嵌套在else语句块中的 只有当外部的if条件不满足,进入else后,才会去判断内部的条件
案例:从键盘输入一个年份值和月份值,输出该月的总天数
要求:年份为正数,月份1-12。
例如:输入2022年5月,总天数是31天。
输入2022年2月,总天数是28天。
输入2020年2月,总天数是29天。
import java.util.Scanner;
public class Test12NestIfElse {
public static void main(String[] args){
//从键盘输入一个年份和月份
Scanner input = new Scanner(System.in);
System.out.print("年份:");
int year = input.nextInt();
System.out.print("月份:");
int month = input.nextInt();
if(year>0){
if(month>=1 && month<=12){
//合法的情况
int days;
if(month==2){
if(year%4==0 && year%100!=0 || year%400==0){
days = 29;
}else{
days = 28;
}
}else if(month==4 || month==6 || month==9 || month==11){
days = 30;
}else{
days = 31;
}
System.out.println(year+"年" + month + "月有" + days +"天");
}else{
System.out.println("月份输入不合法");
}
}else{
System.out.println("年份输入不合法");
}
input.close();
}
}
5 .switch...case多分支选择结构
语法格式:
switch(表达式){
case 常量值1:
语句块1;
【break;】
case 常量值2:
语句块2;
【break;】
。。。
【default:
语句块n+1;
【break;】
】
}
执行过程:
(1)入口
①当switch(表达式)的值与case后面的某个常量值匹配,就从这个case进入;
②当switch(表达式)的值与case后面的所有常量值都不匹配,寻找default分支进入;不管default在哪里
(2)一旦从“入口”进入switch,就会顺序往下执行,直到遇到“出口”,即可能发生贯穿
(3)出口
①自然出口:遇到了switch的结束}
②中断出口:遇到了break等
注意:
(1)switch(表达式)的值的类型,只能是:4种基本数据类型(byte,short,int,char),两种引用数据类型(JDK1.5之后枚举、JDK1.7之后String)
(2)case后面必须是常量值,而且不能重复
1、如何避免case穿透
案例:从键盘输入星期的整数值,输出星期的英文单词
import java.util.Scanner;
public class Test13SwitchDemo1 {
public static void main(String[] args) {
//定义指定的星期
Scanner input = new Scanner(System.in);
System.out.print("请输入星期值:");
int weekday = input.nextInt();
//switch语句实现选择
switch(weekday) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("你输入的星期值有误!");
break;
}
input.close();
}
}
2、利用case的穿透性
在switch语句中,如果case的后面不写break,将出现穿透现象,也就是一旦匹配成功,不会在判断下一个case的值,直接向后运行,直到遇到break或者整个switch语句结束,switch语句执行终止。
练习:根据指定的月份输出对应季节
import java.util.Scanner;
/*
* 需求:指定一个月份,输出该月份对应的季节。
* 一年有四季
* 3,4,5 春季
* 6,7,8 夏季
* 9,10,11 秋季
* 12,1,2 冬季
*/
public class Test14SwitchDemo2 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入月份:");
int month = input.nextInt();
/*
switch(month) {
case 1:
System.out.println("冬季");
break;
case 2:
System.out.println("冬季");
break;
case 3:
System.out.println("春季");
break;
case 4:
System.out.println("春季");
break;
case 5:
System.out.println("春季");
break;
case 6:
System.out.println("夏季");
break;
case 7:
System.out.println("夏季");
break;
case 8:
System.out.println("夏季");
break;
case 9:
System.out.println("秋季");
break;
case 10:
System.out.println("秋季");
break;
case 11:
System.out.println("秋季");
break;
case 12:
System.out.println("冬季");
break;
default:
System.out.println("你输入的月份有误");
break;
}
*/
// 改进版
switch(month) {
case 1:
case 2:
case 12:
System.out.println("冬季");
break;
case 3:
case 4:
case 5:
System.out.println("春季");
break;
case 6:
case 7:
case 8:
System.out.println("夏季");
break;
case 9:
case 10:
case 11:
System.out.println("秋季");
break;
default:
System.out.println("你输入的月份有误");
break;
}
input.close();
}
}
常见错误实现1:
switch(month){
case 3|4|5://3|4|5 用了位运算符,11 | 100 | 101结果是 111是7
System.out.println("春季");
break;
case 6|7|8://6|7|8用了位运算符,110 | 111 | 1000结果是1111是15
System.out.println("夏季");
break;
case 9|10|11://9|10|11用了位运算符,1001 | 1010 | 1011结果是1011是11
System.out.println("秋季");
break;
case 12|1|2://12|1|2 用了位运算符,1100 | 1 | 10 结果是1111,是15
System.out.println("冬季");
break;
default:
System.out.println("输入有误");
}
常见错误实现2:
//编译不通过
switch(month){
case 3,4,5:
System.out.println("春季");
break;
case 6,7,8:
System.out.println("夏季");
break;
case 9,10,11:
System.out.println("秋季");
break;
case 12,1,2:
System.out.println("冬季");
break;
default:
System.out.println("输入有误");
}
3、if语句与switch语句比较
- if语句的条件是一个布尔类型值,if条件表达式为true则进入分支,可以用于范围的判断,也可以用于等值的判断,使用范围更广。switch语句的条件是一个常量值(byte,short,int,char,枚举,String),只能判断某个变量或表达式的结果是否等于某个常量值,使用场景较狭窄。
- 当条件是判断某个变量或表达式是否等于某个固定的常量值时,使用if和switch都可以实现,但是使用switch效率更高。另外,使用switch可以利用穿透性,同时执行多个分支,而if...else没有穿透性。
案例1:只能使用if
从键盘输入一个整数,判断是正数、负数、还是零。
import java.util.Scanner;
public class Test15IfOrSwitchDemo1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.print("请输入整数:");
int num = input.nextInt();
if (num > 0) {
System.out.println(num + "是正整数");
} else if (num < 0) {
System.out.println(num + "是负整数");
} else {
System.out.println(num + "是零");
}
input.close();
}
}
案例2:使用switch效率更高
使用if实现根据星期值输出对应的英文单词
import java.util.Scanner;
public class Test16IfOrSwitchDemo2 {
public static void main(String[] args) {
//定义指定的星期
Scanner input = new Scanner(System.in);
System.out.print("请输入星期值:");
int weekday = input.nextInt();
//使用if...else实现
/*
String weekName = null;
if(weekday == 1) {
weekName = "Monday";
}else if(weekday == 2){
weekName = "Tuesday";
}else if(weekday == 3){
weekName = "Wednesday";
}else if(weekday == 4){
weekName = "Thursday";
}else if(weekday == 5){
weekName = "Friday";
}else if(weekday == 6){
weekName = "Saturday";
}else if(weekday == 7){
weekName = "Sunday";
}
if(weekName != null){
System.out.println(weekday + "对应的单词是" + weekName);
}else{
System.out.println("你输入的星期值有误!");
}*/
//switch语句实现选择
switch(weekday) {
case 1:
System.out.println("Monday");
break;
case 2:
System.out.println("Tuesday");
break;
case 3:
System.out.println("Wednesday");
break;
case 4:
System.out.println("Thursday");
break;
case 5:
System.out.println("Friday");
break;
case 6:
System.out.println("Saturday");
break;
case 7:
System.out.println("Sunday");
break;
default:
System.out.println("你输入的星期值有误!");
break;
}
input.close();
}
}
原理: switch以空间换时间。 1、当分支较多时,当时用switch的效率是很高的。因为switch是随机访问的,就是确定了选择值之后直接跳转到那个特定的分支,但是if…else是遍历所以可能值,直到找到符合条件的分支。如此看来,switch的效率确实比if...else要高的多。 2、由汇编代码可知道,switch…case占用较多的代码空间,因为它要生成跳表,特别是当case常量分布范围很大但实际有效值又比较少的情况,switch…case的空间利用率将变得很低。
案例3:巧用switch的穿透性
用year、month、day分别存储今天的年、月、日值,然后输出今天是这一年的第几天。
注:判断年份是否是闰年的两个标准,满足其一即可
1)可以被4整除,但不可被100整除
2)可以被400整除
例如:1900,2200等能被4整除,但同时能被100整除,但不能被400整除,不是闰年
public class Test17IfOrSwitchDemo3 {
public static void main(String[] args) {
int year = 2021;
int month = 12;
int day = 18;
//判断这一天是当年的第几天==>从1月1日开始,累加到xx月xx日这一天
//(1)[1,month-1]个月满月天数
//(2)单独考虑2月份是否是29天(依据是看year是否是闰年)
//(3)第month个月的day天
//声明一个变量days,用来存储总天数
int days = 0;
//累加[1,month-1]个月满月天数
switch (month) {
case 12:
//累加的1-11月
days += 30;//这个30是代表11月份的满月天数
//这里没有break,继续往下走
case 11:
//累加的1-10月
days += 31;//这个31是代表10月的满月天数
//这里没有break,继续往下走
case 10:
days += 30;//9月
case 9:
days += 31;//8月
case 8:
days += 31;//7月
case 7:
days += 30;//6月
case 6:
days += 31;//5月
case 5:
days += 30;//4月
case 4:
days += 31;//3月
case 3:
days += 28;//2月
//在这里考虑是否可能是29天
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
days++;//多加1天
}
case 2:
days += 31;//1月
case 1:
days += day;//第month月的day天
}
//输出结果
System.out.println(year + "年" + month + "月" + day + "日是这一年的第" + days + "天");
}
}