章三 运算符
事先说下两件事:
- 发现用手机看博客效果蛮差的,毕竟是在电脑上编辑排版的,尽量用电脑看吧,ipad也会有一些变形,不过比手机好些。
- 针对优快云的markdown的问题,下载了一个本地的Markdown软件,用以编辑
使用静态导入(static import),可以简化代码,详见第六章
3.2 使用Java操作符
操作符接受一个或多个参数,并生成一个新值,效果同函数调用。
副作用:改变操作符自身的值。
操作符的意义即生成新值和其副作用
注意:除了=、==和!=这三个操作符能作用于所有对象,+和+=能作用于String,其他所有操作符仅能作用于基本类型,无法重载。
3.3 优先级
说明: 无需刻意去记忆优先级,对于不敢肯定的,加括号以反映思路即可
3.4 赋值
赋值运算符=:将右值复制给左值:
- 右值:常数,变量,表达式(可生成一个值)
- 左值:必须为明确的,已命名变量,即有自己的物理空间用以存储右值
赋值运算符可以作用于基础类型和类对象:
- 基本类型:对于基本类型,赋值操作仅进行拷贝操作
- 类对象:作用于类对象时,赋值操作对对象引用进行操作,产生别名现象:赋值操作仅传递了引用,两个对象引用指向同一对象
注意: 方法调用中参数传递实质上是对类对象进行了赋值操作,也会产生别名现象
3.5 算数运算符
算术运算符: + - * / %五个
复合算术运算符:与赋值运算符结合,+= -= *= /= %=
注意:整数除法结果只保留整数
一元加、减操作符:
1.一元减运算符用以转换数据的符号
2.一元加运算符用以与上述对应,可以将较小类型的操作数提升为int
3.6 自动递增和递减
自动递增和自动递减是两种很好的快捷运算。
其各自有两种形式:
- 前缀式:先进行计算,再生成值
- 后缀式:先生成值,在进行计算
3.7.1 测试对象的等价性
==和!=也适用于所有对象
说明:==和!=比较的是对象引用引用的对象是否相同,而不是对象的内容
比较内容,使用equals()方法。需要说明的是,equals()方法默认使用==来进行比较,若想比较内容需要自己覆盖。String类已覆盖。
练习2.5,2.6:
package chapter3;
public class Dog {
private String name;
private String says;
Dog(String name, String says){
this.name = name;
this.says = says;
}
public static void main(String[] args) {
Dog spot = new Dog("spot","Ruff!");
Dog scruffy = new Dog("scruff","Wurf!");
Dog puppy = spot;
System.out.println(puppy == spot);
System.out.println(puppy.equals(spot));
}
}
输出结果:
true
true
3.8 逻辑操作符
逻辑运算符:与(&&,&),或(||,|),非(!)。根据参数的逻辑关系,生成一个布尔值。
注意:逻辑运算中的参数只能为布尔值
重点:&&和||为短路逻辑运算符,&和|为长路逻辑运算符
3.9 直接常量
tips:
- 通过使用直接常量,编译器可以精确知道生成数的类型
- 直接常量通过后缀字符标识类型
- Java中,二进制数没有直接常量表示方法,但Integer和Long有静态方法toBinaryString()可以进行二进制输出。
后缀或前缀 | 类型 |
---|---|
L或l后缀 | 表示long |
F或f后缀 | 表示float |
D或d后缀 | 表示double |
0x(或0X)前缀 | 表示16进制数 |
0前缀 | 表示8进制数 |
指数计数法:
通过e来记录指数,例如:double d = 4.3e-17;
说明:
- 这里e表示10,而不是自然底数
- 指数计数默认为double类型,可加f后缀转为float类型,其他类型需显示强制转换
练习9:显示用float和double指数计数法所能表示的最大和最小的数
System.out.println(Float.MAX_VALUE);
System.out.println(Double.MAX_VALUE);
System.out.println(Float.MIN_VALUE);
System.out.println(Double.MIN_VALUE);
结果:
3.4028235E38
1.7976931348623157E308
1.4E-45
4.9E-324
3.10 按位操作符
按位操作符:用以操作整型基本数据类型中的单个比特(bit),直接操纵底层硬件
按位操作符会对两个参数中对应的位执行布尔运算,并最终生成一个结果
运算符包括: &(按位与),|(按位或),^(按位亦或);以及其对应的三个复合运算符。
3.11 移位操作符
移位运算符:也用以操作整型基本数据类型中的单个比特(bit)
Java中,有3种移位操作符:
- <<(左移位操作符):按照操作符右侧指定的位数向左移动(低位补零)
- >>(有符号右移操作符):按操作符右侧指定的位数向右移动,采用符号扩展
- >>>(右移操作符):零扩展,无论正负,直接在高位插入0,Java独有
注意事项:
- 移位运算符可以与赋值运算符=组成复合移位运算符
- 对char,byte,short数值进行移位操作,会先将数值转化为int类型,得到int类型结果,再截断,赋值给原类型
- 对于操作符右侧指定位数:对于int类型,仅低5位有效;对于long类型,仅低6位有效。
3.12 三元操作符if-else
三元操作符也叫条件操作符,形式:boolean-expression ? expression0 : expression1
在进行简单判断时,条件操作符比if-else语句更加简洁高效,而且会产生一个值,但可读性较差
3.13 字符串String操作符+和+=
Java不支持运算符重载,+和+=只在String中表示特殊意义。
+操作符在String类中作用:
1. 字符串连接;
2. 字符串转换:当连接元素并非String时,进行toString()转换
注意:如果表达式以一个字符串开始,那么后续所有操作符必须为字符串类型(会执行toString()转换)
程序示例:
String s = "test";
System.out.println(s+1+2);
System.out.println(1+2+s);
输出:
test12
3test
3.14 使用操作符时常犯的错误
常犯的两个错误:
- 运算符=与运算符==混淆,尤其在布尔判断语句中
- 运算符&&,||与运算符&,|混淆,
3.15 类型转换
可以对数值和变量进行类型转换
在Java中:
- 窄化转换(narrowing conversion):必须显示进行类型转换
int i = (int)8L;
- 扩展转换(widening conversion):则无需显式说明
double dd = 4.5f;
3.15.1 截尾和舍入
将浮点型显示转化为整型,编译器采用截尾操作,等价Math.floor()方法
若想四舍五入,则应采用Math.round()方法
说明:Math.floor()返回值为double类型,Math.round()返回值默认为long类型
其他说明:
1. Java中所有基本数据类型在所有机器中大小一致,因此无需sizeof运算符
2. 对char,byte,short进行普通算术运算,得到的结果都为int型
3. 对上述类型进行复合算术运算,无需类型转换
4.要注意算术运算带来的结果值溢出,尤其是乘法
5.除boolean类型外,任意两种基本类型都可以互相转换,其中扩展转换无需显式说明
程序示例:
byte b = 3;
b = b+3; //illegal here, the compiler will report the error;
b += 3; //it's okay. As a quick operation, the explicit conversion can be abbreiated