3. 操作符
3.1 静态导入
- 静态导入:方法中调用静态导入的其他类中的静态方法
package com.one;
public class Print {
public static void print(String s){
System.out.println(s);
}
}
package com.one;
// 静态导入方法
import static com.one.Print.*;
public class TestPrint {
public static void main(String[] args) {
System.out.println("Nomal Print");
// 静态导入的方法输出
print("Simple Print");
}
}
3.2 使用Java操作符
- 副作用:操作符改变操作数本身的值
String类支持"+"和"+="
3.3 优先级
- 优先级顺序
- 先乘除后加减
- 用括号明确计算顺序
3.4 赋值
赋值:使用操作符"="
-
赋值分类
基本类型赋值:直接将内容复制到另一个地方
-
对象类型赋值:将“引用”从一个地方复制到另一个地方(一个对象对应多个引用,一个引用可能有0或1个对象),类似指针,由于原来的指针指向新的对象,所以原来的对象将被垃圾回收器清理,具体可见以下实现
class Tank{ int level; } public class Assignment{ public static void main(String[] args){ // 赋值前 Tank t1 = new Tank(); Tank t2 = new Tank(); t1.level = 9; t2.level = 47; print(t1+","+t2); // 第一次赋值 t1 = t2; print(t1+","+t2); // 第二次赋值 t1.level = 22; print(t1+","+t2); } } /* output: 9,47 47,47 22,22 */
-
别名现象解析
代码片段(见赋值分类的对象类型赋值)
-
原理分析
第一次赋值是将t2的指向修改为与t1一致,同时指向同一个对象,因为t1和t2都是引用
-
第二次赋值是将t1和t2指向的同一个对象中的level值修改了
[图片上传失败...(image-83be4-1563342666109)]
3.5 算术操作符
-
操作符种类
- 加号+、减号-、除号/、乘号*,取模%
- 整数除法会直接去掉结果的小数位,不会四舍五入
-
Random方法
Random为生成伪随机数的类,使用nextInt()/nextFloat()方法获取随机数
-
如果种子参数相同,则生成的随机数也相同,见下方
package com.four; import java.util.Random; public class TestRandom { public static void main(String[] args) { // 种子数相同 Random random1 = new Random(10); Random random2 = new Random(10); int i = random1.nextInt(); int j = random2.nextInt(); System.out.println("i="+i); System.out.println("j="+j); } } /* output: i=-1157793070 j=-1157793070 */
3.5.2 一元加、减操作符
一元减号:转变数据的符号,或修改数据类型
-
一元加号:将数据类型修改为int类型
package com.four; public class TestAdd { public static void main(String[] args) { int i = 1; char j = 'c'; short k = 5; System.out.println(i); System.out.println(j); System.out.println(k); System.out.println("添加加号"); System.out.println(+i); System.out.println(+j); System.out.println(+k); System.out.println("添加减号"); System.out.println(-i); System.out.println(-j); System.out.println(-k); } } /* output 1 c 5 添加加号 1 99 5 添加减号 -1 -99 -5 */ // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/four/TestAdd.java
3.6 自动递增和递减
-
分类
前缀递增、前缀递减:先执行运算,后生成值
-
后缀递增、后缀递减:先生成值,后执行运算
package com.four; import static util.Print.*; public class TestIncreasing { public static void main(String[] args) { int i = 1; int j = i; print("i = "+i); // 前缀递增 j = ++i; print("前缀递增后"); print("i = "+i); print("j = "+j); i = 1; j = i; // 前缀递减 j = --i; print("前缀递减后"); print("i = "+i); print("j = "+j); i = 1; j = i; // 后缀递增 j = i++; print("后缀递增后"); print("i = "+i); print("j = "+j); i = 1; j = i; // 后缀递减 j = i--; print("后缀递减后"); print("i = "+i); print("j = "+j); i = 1; j = i; } } /* output i = 1 前缀递增后 i = 2 j = 2 前缀递减后 i = 0 j = 0 后缀递增后 i = 2 j = 1 后缀递减后 i = 0 j = 1 */ // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/four/TestIncreasing.java
3.7 关系操作符
- 分类
- 大于、小于、大于等于、小于等于、等于(==)、不等于(!=)
- 等于和不等于适用所有基本数据类型,其他比较符不使用boolean类型
3.7.1 对象的等价性
-
==和!=比较的是对象的引用
package com.five; public class TestEquals { public static void main(String[] args) { // 使用==比较 基本数据类的相同内容的不同对象 Integer n1 = new Integer(47); Integer n2 = new Integer(47); System.out.print("使用==比较 相同内容的不同对象:"); System.out.println(n1 == n2); // 使用equals比较 基本数据类的相同内容的不同对象 System.out.print("使用equals比较 相同内容的不同对象:"); System.out.println(n1.equals(n2)); // 使用==比较 自定义类的相同内容的不同对象 Dog dog1 = new Dog(); dog1.setName("spot"); dog1.setSays("Ruff!"); Dog dog2 = new Dog(); dog2.setName("spot"); dog2.setSays("Ruff!"); System.out.print("使用==比较 自定义类的相同内容的不同对象:"); System.out.println(dog1 == dog2); // 使用equals比较 自定义类的相同内容的不同对象 System.out.print("使用equals比较 相同内容的不同对象:"); System.out.println(dog1.equals(dog2)); } } /* output 使用==比较 相同内容的不同对象:false 使用equals比较 相同内容的不同对象:true 使用==比较 自定义类的相同内容的不同对象:false 使用equals比较 相同内容的不同对象:false */ // /Users/toyz/Package/Note/Thinking in Java/Practice/Operators/src/com/five/TestEquals.java
-
总结
- == 对于基本数据类型,是比较值;对于引用数据类型,是比较地址
- equals 对于引用的基本数据类型的比较生效,适合比较对象内容,而非比较对象的引用
3.8 逻辑操作符
- 分类
- 与(&&)、或(||)、非(!)
- 以上三种只能应用于布尔值
- 在String值的地方使用布尔值,布尔值会自动转换成适当的文本
3.8.1 短路
定义:当能够确定一个表达式的值,就不计算余下的部分
-
演示过程:当判断到(j<2)时为false时,程序不会执行后续判断,直接输出false
package com.seven; import static util.Print.*; public class ShortCircuit { public static void main(String[] args) { int i = 1; int j = 2; int k = 3; print("res:"+((i<2)&&(j<2)&&(k<2))); } }
3.9 直接常量
直接常量的后缀字符标注了类型
- 常用类型
- L代表long
- F代表Float
- D代表Double
- 十六进制数字:以前缀0x,后面跟随0~9或小写的a~f来表示
- 八进制数字:以前缀0,后面跟随0~7数字来表示
3.9.1 指数计数法
程序设计时使用e代表“10的幂次”,但是在科学和工程领域,e代表自然对数的基数
3.10 按位操作符
-
运算方式
- &、|、^、~
- 与、或、异或、取反
- **异或:相同则为零,不同则为1 **
-
运算规则
- &: 1&1=1 , 1&0=0 , 0&1=0 , 0&0=0
- |: 1|1=1 , 1|0=1 , 0|1=1 , 0|0=0
- ^: 1^1=0 , 1^0=1 , 0^1=1 , 0^0=1
- ~: ~1=0 , ~0=1
-
进制运算
-
二进制转为十六进制:小数点左边向左开始,右边向右开始,各取4位,不足的向左(向右)补零
- 二进制:010101 —— 十六进制:15
- 第一步:二进制分为:01,0101
- 第二步:补全:0001,0101
- 第三步:0001为1,0101为5(计算的时候要把顺序倒过来,0101看成1010计算)
-
二进制转为十六进制:小数点左边向左开始,右边向右开始,各取4位,不足的向左(向右)补零
-
使用二进制表示负数
获得原码:00101111
获得反码:11010000
获得补码(反码加一):11010001
3.11 移位操作符
- 左移操作符(<<):操作数向左移动,低位补零
- 右移操作符(>>):操作数向右移动,当符号为正,高位补零;当符号为负,高位补1
- 无符号右移操作符(>>>):无论正负,都在高位插入零
byte和short类型使用位移运算时,会先转换成int类
3.12 三元操作符
-
if-else操作符,形式为boolean-eep ? value1 : value2
当结果为true时,就计算value1;当结果为false,就计算value2
使用时需要注意可读性
3.13 字符串操作符+和+=
- 需要考虑计算的优先级
package com.thirteen;
import static util.Print.*;
public class PrintString {
public static void main(String[] args) {
int x = 0 , y = 1 , z = 2;
String s = "x,y,z";
System.out.println(s+x+y+z);
System.out.println(s+(x+y+z));
System.out.println(x+y+z+s);
System.out.println(x+""+s);
System.out.println(""+x);
System.out.println(x+y+z);
}
}/* output
x,y,z012
x,y,z3
3x,y,z
0x,y,z
0
3
*/
3.15 类型转换操作符
- 窄化转换:将能容纳更多信息的数据类型转化成无法容纳这么多信息的数据类型,存在风险
- 扩展转换:新类型能够容纳更多信息,安全,不会造成任何信息的丢失
Java允许将任何基本数据类型转换成别的基本数据类型,但布尔类型不允许任何转换
“类”数据类型不允许类型转换,除非使用特殊方法
3.15.1 截尾和舍入
-
截尾
- float和double转换成整型
-
舍入
- 使用java.lang.Math中的round()方法
3.15.2 提升
表达式中的最大数据类型决定了表达式最终结果的数据类型
3.16 Java没有sizeof
所有数据类型在所有机器中的大小都是相同的