运算符
一种特殊的符号,用以表示数据的运算、赋值和比较等
算数运算符
对数值类型变量进行计算,与寻常的数学运算符相比有三点不同
- 寻常的除(也就是/)被分解成了取整/ 和取余%,分别对应除法运算后的整数和小数部分
- 寻常的+ 在遇到字符串时会进行拼接运算
- 多出了自增++ 和自减-- 运算符,并根据出现的位置决定其执行顺序
运算过程中遵循自动提升原则,也就是表达式的结果类型为操作数中的最大类型
关系运算符
运算结果是boolean类型,即true或false,由关系运算符组成的表达式被称为关系表达式。常用于选择结构或循环结构的条件,与寻常的比较远算符(>、<...)相比有两点不同
- 使用双等于(==)实现等值判断,单等于(=)是赋值
- 多出了instanceof实现类型判断,比如a instanceof Integer 可以判断a是否为Integer类型
使用instanceof进行类型判断的本质其实是判断左侧对象是否为右侧类的实例,因此左右两侧需要是引用类型。
逻辑运算符
运算结果是boolean类型,用于连接多个关系表达式。与寻常数学中的逻辑运算符相比有两点不同
- Java中的逻辑运算符为与 - &,或 | ,非 !,异或 ^
- 逻辑运算符中的&、| 成对出现时就成为短路运算符
异或^仅当两侧不同时才会返回true。
短路运算符的特点是只要能判断出结果就不会执行后续的关系表达式。效率上优于对应的逻辑运算符
赋值运算符
将某个运算之后的结果赋给指定变量,可以分为两类
- 基本赋值运算符:=
- 复合赋值运算符:算术运算符 + =,比如+=、-=...
复合赋值运算符的本质是简化书写,比如a = a + 1等价于 a += 1。并且由于期间涉及到表达式运算,所以可能会进行类型转换。
三元运算符
基本格式为: 条件表达式 ? 表达式1 : 表达式2
运算规则为:条件表达式结果为true,执行表达式1,反之执行表达式2
三元运算符中表达式的结果要为可以赋给接收变量的类型。
位移运算符
将二进制数整体向右(>>)或向左(<<)移动指定位数。空位补0,,>>需要补符号位
二进制数的最高位为符号位,0表示正数、1表示负数
优先级
运算符的优先级对应表达式中的运算顺序
通常情况下,运算符的优先级遵循自然规则(比如先乘除后加减...),并且只有单目运算符和赋值运算符是从右至左。如果需要更明显地确定执行顺序,可以适当使用括号
标识符
标识符就是Java中对变量、类、方法等命名时使用的字符序列,标识符的命名规则如下:
- 由字母、数字、下划线、美元符组成
- 不能以数字开头
- 不能以 关键字/保留字 作为标识符
- 严格区分大小写
之所以标识符不能使用关键字或者保留字,是因为它们在Java中具有特殊含义
除了命名规则之外,为了使代码更具可读性和便于管理,衍生出了如下命名规范:
- 包名使用小写
- 类名、接口名使用大驼峰命名,即包括首字母在内的单词首字母大写
- 变量名、方法名使用小驼峰命名,即除首字母之外的单子首字母大写
- 常量名都使用大写,如果单词数大于1 则使用下划线连接
键盘输入
通过使用Scanner(扫描器) 这个API可以实现对用户输入数据的接收
API使用流程:导入对应包 + 获取实例对象 + 调用功能方法
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("请输入你的年龄:");
int age = scanner.nextInt();
System.out.println("你今年" + age + "岁");
}
}
进制转换
对于整数,有四种常见的进制表示:二进制、八进制、十进制以及十六进制
进制的规则是:几进制就是满几进一,比如八进制就是满八进一
不同进制的表示方法如下:
- 二进制:以0b或0B开始
- 八进制:以0开始
- 十进制:正常
- 十六进制:以0x或0X开始
十六进制中除了0-9之外,其余的六个使用A-F表示
进制转换规则如下:
- 其他进制转十进制:从最低位开始,每一位乘以进制数的位数减一次方,最后求和
- 十进制转其他进制:将该数不断除以进制数,直到商为0,最后将余数反转
- 二进制转八/十六 进制:将二进制数每三/四 位一组,转换为对应的进制数
- 八/十六 进制转二进制:将八/十六 进制的每一位转为三/四 位二进制数
位运算
原码、反码和补码
规则如下:
- 正数的三码相同
- 负数的反码等同于原码除符号位外按位取反
- 负数的补码等同于反码减一
- 计算机在运算的时候是以补码的方式来运算的,而查看运算结果时则是看原码
位运算符
- 按位与:& -> 全一则一
- 按位或:| -> 有一则一
- 按位异或:^ -> 不同则一
- 按位取反:~
- 算数右移:>> -> 符号位不变补高位
- 算数左移:<< -> 符号位不变,低位补0
- 逻辑右移:>>> -> 高位补0
流程控制
顺序控制
程序从上至下执行,期间无判断或跳转
分支控制
根据条件表达式的值判断是否进入该分支,而根据分支数量的不同又可以分为if 单分支、if...else双分支以及if...else if...多分支
只有前一个分支不满足条件才会判断下一个分支是否执行,在整个分支控制中最多只有一个执行入口。如果分支以else 结尾,则所有条件表达式都不满足的情况下会默认执行此分支
如果在一个分支结构中完整的嵌套了另一个分支结构,则两个分支分别作为外层分支和内层分支,这也被成为嵌套分支。为了保证可读性,通常分支嵌套不超过三层
除了if...else...之外,还可以使用switch分支结构,由以下几部分组成:
- 表达式:对应一个值
- case 常量:用于匹配表达式值,匹配成功则执行之后的语句块
- default:没有case能匹配后默认执行其后的语句块
- break:执行结束,退出switch
在使用switch时需要注意以下几点:
- case子句中的值必须是常量
- 表达式的返回值必须是byte、short、int、char、enum、String
- 表达式的数据类型应该与case后常量的类型一致,或者是可以自动转型的类型
- 如果没有写break,程序会一直执行,直到退出switch
对于if和switch的选择,如果是具体值的判断则多使用switch,如果是区间判断或结果是boolean类型则多使用if
循环控制
通过循环控制可以实现某一段代码的反复执行
for循环
for(循环变量初始化; 循环条件; 循环变量迭代) {
循环体;
}
如果循环体只有一行语句,则可以省略大括号(但不建议)
- 循环条件是结果为boolean类型的表达式
- 循环变量初始化和迭代可以写在其他地方,但是分号不能省略
- 循环变量初始化和迭代可以有多条,中间使用逗号隔开
while循环
循环变量初始化;
while(循环条件) {
循环体;
循环变量迭代;
}
与for循环相比,只是循环变量、循环条件、循环体、循环变量迭代的位置发生了变化
do..while循环
循环变量初始化;
do{
循环体;
循环变量迭代;
}while(循环条件);
与while循环相比同样只是四要素的位置发生了变化,这也导致do..while循环至少会先执行一次循环体
与分支控制一样,循环控制同样可以实现嵌套。本质上就是将内层循环作为外层循环的循环体,只有内层循环结束,才会跳出内层循环转而进入下一轮外层循环
练习题:打印空心三角形(层数由用户输入)
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// 获取行数
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the number of rows:");
int total = scanner.nextInt();
// 外层循环,控制每层输出
for (int i = 1; i <= total; i++) {
// 输出空格,规则为4、3、2、1、0,即total - i
for (int j = 1; j <= total - i; j++) {
System.out.print(" ");
}
// 输出星号,规则为开始和结尾,以及最后一层
for (int k = 1; k <= 2 * i - 1; k++) {
if (k == 1 || k == 2 * i - 1 || i == total) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
// 每层输出结束后换行
System.out.println();
}
}
}
跳转控制
break语句可以用于终止某个语句块的执行,一般用在switch或者循环中。用以实现当满足某个条件的时候退出当前switch或者循环
在嵌套循环中,break可以用于退出最近的循环体,或者使用label退出到指定位置(不建议使用)
continue语句可以用于结束本次循环,继续执行下一次循环
与break类似,continue同样可以跳过最近的循环体执行而进入下一次循环,亦可使用label控制跳过哪一层循环(不建议使用)
return语句可以用于方法,表示退出当前方法或者返回指定值