第三章 操作符
在最底层,Java中的数据是通过使用操作符来操作的
Java是建立在C++基础之上的,Java大部分和C++相似,但是也做了一些改进和简化
3.1 更简单的打印语句
静态导入一个小类库可以简化打印语句
练习1、分别使用简短的和正常的打印语句
public class E01_PrintStatements { public static void main(String[] args) { Date currDate = new Date(); System.out.println("Hello, it's: " + currDate); print("Hello, it's: " + currDate); } }
3.2 使用Java操作符
- 加减乘除、正号负号、=等等
- 几乎所有的操作符都只能操作基本类型
- =、==、!=、可以操作所有的对象
- String类支持 +、+=
3.3 优先级
最简单的加减乘除不用提了,而其他的逻辑运算符也差不多,编程中几乎不太会有这方面的问题,因为如果你写错会有提示的
3.4 赋值
1、基本数据类型的赋值就是直接存储了实际的数值,并不是引用
a = 1; b = 2; c = 3; a = c; b = c; // 那么abc都为3,无论如何操作a和b,对c都没有任何影响
2、而在为对象赋值的时候,却不一样,持有了引用,只要引用一变,就都变
// 新建三个城市类,参数为该城市的人数 City cityA = new City(100); City cityB = new City(200); City cityC = new City(300); cityA = cityC; cityB = cityC; cityA.number = 1000; // cityA、cityB、cityC都持有“有300个人的城市”的引用 // cityA将人口变为1000,那么cityA、cityB、cityC的人数都变为了1000 // 而“有100个人的城市”、“有200个人的城市”将不会被引用,会被垃圾回收器自动清理
练习2:展示别名机制
class Integral { float f; } public class E02_Aliasing { public static void main(String[] args) { Integral n1 = new Integral(); Integral n2 = new Integral(); n1.f = 9f; n2.f = 47f; print("1: n1.f: " + n1.f + ", n2.f: " + n2.f); n1 = n2; print("2: n1.f: " + n1.f + ", n2.f: " + n2.f); n1.f = 27f; print("3: n1.f: " + n1.f + ", n2.f: " + n2.f); } }
3.4.1 方法调用中的别名问题
在方法中传递,并不是复制了一个副本,而是传了一个引用
某某方法通过参数中的这个引用操作了这个对象,改变的就是这个对象的值
class City { int number; } class CityManager { static void changeNumber(City city) { city.number = 250; } } class Main { public static void main(String[] args) { City cityA = new City(); cityA.number = 100; CityManager.changeNumber(city); print("最终的城市人口数为:" + cityA.number); } } // 最后的结果将会是250,changeNumber(city)这个方法会把整个对象的值改变了 // 初学者爱犯的错误: // 认为只是将参数的值改了,改变后的值就只能在这个方法内使用 // 出了这个方法以后就又变到原来的值了 // 别问我为什么这么清楚,因为我以前就是这样认为的,哈哈哈~
练习3、展示方法调用时的别名机制
public class E03_Aliasing2 { static void f(Integral y) { y.f = 1.0f; } public static void main(String[] args) { Integral x = new Integral(); x.f = 2.0f; print("1: x.f: " + x.f); f(x); print("2: x.f: " + x.f); } }
3.5 算术操作符
+、-、*、/、%、+=等等
练习4、编写一个计算速度的程序,时间和距离都是常量
public class E04_Velocity { public static void main(String[] args) { if(args.length < 2) { System.err.println("Usage: java E04_Velocity distance time"); System.exit(1); } float distance = Float.parseFloat(args[0]); float time = Float.parseFloat(args[1]); System.out.print("Velocity = "); System.out.print(distance / time); System.out.println(" m/s"); } }
3.5.1 一元加、减操作符
正号和负号
3.6 自动递增递减
++,--,一种是前缀,一种是后缀,比较简单不说啦
3.7 关系操作符
生成boolean类型的值,<、>、>=、<=、==、!=
3.7.1 测试对象的等价性
==和!=比较的是对象的引用
City cityA = new City(100); City cityB = new City(100); cityA == cityB // 这个值肯定返回的是false; // 两个城市的人口都是100,并不能确定他们就是同一个城市
比较内容是否相同:
- 基本类型直接使用==
- 而其他对象必须使用equals来比较内容是否相同
- equals的默认行为是比较引用,如果自定义的类,我们想要比较内容是否相等,得去重写equals方法
- 大多数类库都实现了equals()方法,用来比较对象的内容,而不是比较对象的引用
练习5、创建Dog类,拥有Stirng类型的name和says,并创建两个对象,赋予它们相应的值并打印出来
class Dog { String name; String says; } public class E05_Dogs { public static void main(String[] args) { Dog dog1 = new Dog(); Dog dog2 = new Dog(); dog1.name = "spot"; dog1.says = "ruff!"; dog2.name = "scruffy"; dog2.says = "wurf!"; System.out.println(dog1.name + " says " + dog1.says); System.out.println(dog2.name + " says " + dog2.says); } }
练习6、在练习5的基础上,测试==和equals()方法来比较结果
public class E06_DogsComparison { static void compare(Dog dog1, Dog dog2) { print("== on top references: " + (dog1 == dog2)); print("equals() on top references: " + dog1.equals(dog2)); print("== on names: " + (dog1.name == dog2.name)); print("equals() on names: " + dog1.name.equals(dog2.name)); print("== on says: " + (dog1.says == dog2.says)); print("equals() on says: " + dog1.says.equals(dog2.says)); } public static void main(String[] args) { Dog dog1 = new Dog(); Dog dog2 = new Dog(); Dog dog3 = dog1; // "Aliased" reference dog1.name = "spot"; dog1.says = "ruff!"; dog2.name = "scruffy"; dog2.says = "wurf!"; print("Comparing dog1 and dog2 objects..."); compare(dog1, dog2); print("\nComparing dog1 and dog3 objects..."); compare(dog1, dog3); print("\nComparing dog2 and dog3 objects..."); compare(dog2, dog3); } } // 运行结果显而易见: // compare(dog1, dog3)返回的都是true // 剩下两个返回的结果都是false
3.8 逻辑操作符
与或非,&&、||、!
练习7、模拟抛硬币的结果
public class E07_CoinFlipping { public static void main(String[] args) { Random rand = new Random(47); boolean flip = rand.nextBoolean(); System.out.print("OUTCOME: "); System.out.println(flip ? "HEAD" : "TAIL"); } }
3.8.1 短路
逻辑运算的时候如果前面的为false,后面的就不执行下去了,这个很好理解
3.9 直接常量
int、char、byte、short、long、float、double都可以用直接常量
练习8、用十六进制和八进制计数法来操作long值
public class E08_LongLiterals { public static void main(String[] args) { long l1 = 0x2f; // Hexadecimal (lowercase) print("l1: " + Long.toBinaryString(l1)); long l2 = 0X2F; // Hexadecimal (uppercase) print("l2: " + Long.toBinaryString(l2)); long l3 = 0177; // Octal (leading zero) print("l3: " + Long.toBinaryString(l3)); } }
3.9.1 指数计数法
简单的说,在Java中,e表示10的幂次
练习9、分别显示用float和double指数计数法所能表示的最大和最小的数字
public class E09_MinMaxExponents { public static void main(String[] args) { print("Float MIN: " + Float.MIN_VALUE); print("Float MAX: " + Float.MAX_VALUE); print("Double MIN: " + Double.MIN_VALUE); print("Double MAX: " + Double.MAX_VALUE); } }
3.10 按位操作符
二进制位的操作,与或非异或,和逻辑运算符的区别是只使用了一个符号,并且不会短路
练习10、二进制的一个操作
public class E10_BitwiseOperators { public static void main(String[] args) { int i1 = 0xaaaaaaaa; int i2 = 0x55555555; print("i1 = " + Integer.toBinaryString(i1)); print("i2 = " + Integer.toBinaryString(i2)); print("~i1 = " + Integer.toBinaryString(~i1)); print("~i2 = " + Integer.toBinaryString(~i2)); print("i1 & i1 = " + Integer.toBinaryString(i1 & i1)); print("i1 | i1 = " + Integer.toBinaryString(i1 | i1)); print("i1 ^ i1 = " + Integer.toBinaryString(i1 ^ i1)); print("i1 & i2 = " + Integer.toBinaryString(i1 & i2)); print("i1 | i2 = " + Integer.toBinaryString(i1 | i2)); print("i1 ^ i2 = " + Integer.toBinaryString(i1 ^ i2)); } }
3.11 移位操作符
操作对象也是二进制的位,只能处理整型
练习11、右移
public class E11_SignedRightShift { public static void main(String[] args) { int i = 0x80000000; print(Integer.toBinaryString(i)); i >>= 1; print(Integer.toBinaryString(i)); i >>= 1; print(Integer.toBinaryString(i)); i >>= 1; print(Integer.toBinaryString(i)); i >>= 1; print(Integer.toBinaryString(i)); } } /* Output: 10000000000000000000000000000000 11000000000000000000000000000000 11100000000000000000000000000000 11110000000000000000000000000000
练习12、先左移再右移
练习13、二进制形式显示char类型的值
这俩略了,差不多就这个意思,弄了半天,主要是用了Integer.toBinaryString()方法
3.12 三元操作符 if-else
boolean ? value1 : value2
使用三元操作符代码会更简洁,但是可读性有点差,选择使用的时候请考虑
3.13 字符串操作符 + 和 +=
如果表达式以字符串开头,那么后续操作数都必须是字符串型,编译器会自动转换
3.14 使用操作符时常犯的错误
没啥说的,多注意吧
3.15 类型转换操作符
基本类型可以相互转换,所属类型可以相互转换
3.15.1 截尾和舍入
默认总会截尾,想要舍入使用Math中的round()方法
3.16 Java没有sizeof
Java不必考虑移植的问题
3.17 操作符小结
boolean的运算十分有限,只能true或者false
char、byte、short中,只要进行算术运算返回的都是int结果,必须将其转换回原来的类型
练习14、编写一个接受两个字符串参数的方法
略
3.18 总结
没啥说的啦,哈哈哈~