「Java教案」算术运算符与表达式
课程目标
1.知识目标
- 能够区分Java运算符的种类,例如,算术、赋值、关系、逻辑、位运算等。
- 能够区分Java各类运算符的功能和使用场景。
- 能够根据表达式的构成和计算规则,写出正确的表达式。
- 能够根据运算符优先级与结合性,正确写成符合需求的表达式。
2.能力目标
- 能根据程序需求正确编写包含复合运算符的表达式。
- 能根据运算符优先级规则优化代码逻辑。
3.思政目标
- 培养严谨细致的编码习惯。
- 强调代码规范与可读性。
- 激发逻辑思维与问题拆解能力。
教学内容
1.运算符分类
- 算术运算符:+、-、*、/、%
- 赋值运算符:=、+=、-=、*=、/=
- 关系运算符:==、!=、>、<、>=、<=
- 逻辑运算符:&&、||、!
- 位运算符:&、|、^、~、<<、>>
2.表达式
- 表达式的定义与组成
- 表达式的计算规则
3.运算符优先级与结合性
- 优先级规则
- 结合性规则
重点分析
难点分析
教学活动设计
概念引入
1.运算符分类与功能
运算符是用于执行特定数学或逻辑操作的符号。Java提供了丰富的运算符集,可以分为以下几类:
- 算术运算符:用于基本的数学运算
基础运算符:+(加)、-(减)、*(乘)、/(除)、%(取模-求余数)
复合运算符:++(自加)、--(自减)
int a = 10, 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
- 比较运算符:用于比较两个数的值,返回的结果为true(真)和false(假)。包括,==(等于)、!=(不等于)、>(大于)、<(小于)、>=(大于等于)、<=(小于等于)
int x = 5, y = 10;
System.out.println(x == y); // false
System.out.println(x != y); // true
System.out.println(x > y); // false
- 逻辑运算符:用于布尔逻辑运算,返回的结果为true(真)和false(假)。
逻辑与:&&(短路行为,左侧表达式的值为false时,右侧表达式跳过不运行)
逻辑或:||(短路行为,左侧表达式的值为true时,右侧表达式跳过不运行)
逻辑非:!
boolean t = true, f = false;
System.out.println(t && f); // false
System.out.println(t || f); // true
System.out.println(!t); // false
- 位运算符:对整数进行位级运算。
按位操作:&(与)、|(或)、^(异或)、~(取反)
位移操作:<<(左移,例如1 << 3结果为8)、>>(右移,例如8 >> 2结果为2)、>>>(无符号右移)
int num1 = 5; // 0101
int num2 = 3; // 0011
System.out.println(num1 & num2); // 1 (0001)
System.out.println(num1 | num2); // 7 (0111)
System.out.println(num1 << 1); // 10 (1010)
- 赋值运算符:给变量赋值
直接赋值:=
复合赋值:+=(加后赋值)、-=(减后赋值)、*=(乘后赋值)、/=(除后赋值)、%=(取模后赋值)、&=(位与后赋值)、|=(位或后赋值)、^=(位异或后赋值)、<<=(左移后赋值)、>>=(右移后赋值)、>>>=(无符号右移后赋值)
int age = 20;
String status = (age >= 18) ? "成人" : "未成年";
System.out.println(status); // 成人
2.表达式与求值规则
- 表达式是由变量、运算符、方法调用等组成的语法结构,它能计算得到一个确定的值。
- 表达式的基本特征
表达式由操作数和运算符组成:如a + b中,a和b是操作数,+是运算符。
表达式计算后会得到一个特定类型的值。
表达式中可以包含其他表达式。
表达式的结果可以赋给变量。
- 表达式的类型:
算术表达式:由算术运算符组成的表达式。
int result = 10 + 5 * 3; // 结果为25
double area = Math.PI * 10 * 10; // 结果为:314.1592653589793
关系表达式:比较两个值的关系,返回布尔值。
boolean isEqual = (10 == 20); // 结果:false
boolean isGreater = (10 > 5); // 结果:true
逻辑表达式:由逻辑运算符组成,返回布尔值。
boolean isValid = (20 >= 18) && (false); // 结果:false
boolean isTrue = !(10 == 10); // 结果:false
赋值表达式:包含赋值运算符的表达式。
int x = 10; // 简单赋值
x += 5; // 复合赋值
- 表达式的求值顺序规则
运算符优先级:优先级高的运算符先计算。
结合性:相同优先级的运算符按结合方向计算。
括号优先:括号内的表达式先计算。
int result = 5 + 3 * 2; // 先乘后加,结果为11
int result2 = (5 + 3) * 2; // 先括号内,结果为16
3.数据类型转换规则
Java中的数据类型转换分为两大类:自动类型转换(隐式转换)和强制类型转换(显式转换)。
- 自动类型转换(隐式转换/Widening Conversion)
当满足以下条件时,Java会自动进行类型转换:①两种数据类型兼容;②目标类型比源类型范围更大。
数值类型的自动转换顺序
转换规则:①小容量类型自动转换为大容量类型;②char可以自动转换为int及以上类型;③byte、short、char参与运算时自动提升为int。
示例:
int a = 100;
long b = a; // 自动转换
float c = b; // 自动转换char ch = 'A';
int i = ch; // 自动转换,i=65
示例:自动转换的特殊情况
byte b = 42;
char c = 'a';
short s = 1024;
int i = 50000;
float f = 5.67f;
double d = .1234;// 表达式中的自动提升
double result = (f * b) + (i / c) - (d * s);
// b自动转为float,c自动转为int,s自动转为double
- 强制类型转换(显式转换/Narrowing Conversion)
当要将大范围类型转换为小范围类型时,必须使用强制类型转换。
基本语法:(targetType) value
数值类型的强制转换
double d = 100.04;
long l = (long)d; // l=100,小数部分截断
int i = (int)l; // i=100float f = 3.14f;
short s = (short)f; // s=3
可能的数据丢失
int i = 257;
byte b = (byte)i; // b=1 (因为byte范围是-128~127)
// 257-256=1double d = 300.678;
int f = (int)d; // f=300,小数部分丢失
char的特殊转换
int i = 65;
char ch1 = (char)i; // ch1='A'byte b = 66;
char ch2 = (char)b; // ch2='B'
- 表达式中的类型提升规则
byte、short、char自动提升为int:
byte a = 40;
byte b = 50;
byte c = a + b; // 错误!a+b自动转为int
byte d = (byte)(a + b); // 正确
表达式中最高级的类型决定最终类型
int i = 10;
long l = 100;
float f = 3.5f;
double d = 4.5;double result = i + l + f + d; // 全部提升为double
4.运算符优先级及结合性
运算符优先级决定了表达式中运算符的执行顺序。当表达式包含多个运算符时,优先级高先计算。如果运算符优先级相同,再根据运算符的结合性(从左到右或从右到左)来决定计算顺序。
运算符优先级表(从高到低)
案例解析
案例1:计算商品折扣价(含类型转换)
public class Test {public static void main(String[] args) {double price = 100.0;int discountRate = 20; // 折扣率20%double finalPrice = price * (1 - discountRate / 100.0); // 关键:100.0强制类型转换System.out.println("最终价格: " + finalPrice); // 输出80.0}
}
运行结果
最终价格: 80.0
discountRate / 100.0中,100.0将整数除法转为浮点除法。
案例2:判断闰年(含逻辑运算符优先级)
public class Test {public static void main(String[] args) {int year = 2025;boolean isLeap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);System.out.println(year + "年是闰年吗?" + isLeap); // 输出true}
}
运行结果
2025年是闰年吗?false
&&优先级高于||,但用括号明确条件分组更清晰。
常见错误
错误:混淆=与==
if (x = 5) { ... } // 编译错误:无法将int转为boolean
解决方法:强调=是赋值,==是相等比较。
错误:忽略优先级导致逻辑错误
int a = 3, b = 4, c = 5;
boolean result = a > b && b < c; // 实际计算顺序:先a>b(false),再false && ...(短路)
解决方法:用括号强制优先级,如(a > b) && (b < c)。
错误:位运算符号混淆
int x = 5;
int y = x & 2; // 按位与,结果为0(5的二进制101 & 2的二进制010)
System.out.println(y); // 输出0
解决方法:通过二进制表对比&、|、^的差异。
课堂练习
练习:计算表达式int x = 5; int y = x++ * 2 + --x;的值。
参考答案:y = 15(x++先赋值后自增,--x先自减后使用)。
练习:用位运算实现交换两个变量(不借助临时变量)。
参考答案:
public class Test {public static void main(String[] args) {int a = 10, b = 20;System.out.println("交换前:a = " + a + ", b = " + b);a ^= b;b ^= a;a ^= b; // 交换后a=20, b=10System.out.println("交换后:a = " + a + ", b = " + b);}
}
运行结果
交换前:a = 10, b = 20
交换后:a = 20, b = 10
练习:修复错误代码
int num = 10;
if (num = 20) { // 错误:赋值运算符误用System.out.println("num等于20");
}
参考答案:
int num = 10;
if (num == 20) { // 错误:赋值运算符误用System.out.println("num等于20");
}
课后作业
作业:编写程序,判断用户输入的年份是否为世纪年且闰年(如2000年)。
参考答案
public class Test {public static void main(String[] args) {int year = 2000;boolean isCenturyLeap = (year % 400 == 0);System.out.println(isCenturyLeap);}
}
运行结果
true
作业:解释1 << 3的含义,并写出其二进制运算过程。
参考答案:1 << 3是Java中的左移运算符,表示将数字1的二进制形式向左移动3位,并在右侧补0。
运算结果:1 << 3 = 8(十进制)
说明:左移运算常用于高效计算2的幂次方,或位掩码(Bitmask)操作。
考核设计
1.过程性考核(40%)
- 课堂练习的完成程度(20%)
- 编写代码的规范性与添加注释的规范性(10%)
- 参与小组讨论和解决问题的能力(10%)
2.终结性考核(60%)
- 理论测试(20%)
- 综合项目(40%)
理论测试:
填空题:计算表达式5 + 3 * 2 / 4 - 1的值为________。
答案:5 + 6 / 4 - 1 = 5 + 1 - 1 = 5(整数除法结果为1)。
选择题:以下哪个表达式可能会触发短路行为?
A.if (a > 0 || b++) B.if (a > 0 && b++)
答案:B(当a > 0为false时,b++不会执行)。
简答题:解释x ^= y ^= x ^= y的交换逻辑。
答案:通过三次异或运算实现交换,但可读性差,建议使用临时变量。
综合项目:
任务:编写程序,计算表达式(a + b) * c / d % e的值,并验证优先级规则。
示例:
int a = 5, b = 3, c = 2, d = 4, e = 2;
System.out.println((a + b) * c / d % e);