Java 的数据是通过操作符来操作的。几乎所有操作符都只能操作“基本类型”,但“=”、“==“和”!=“能操作所有对象。String支持”+“和”+=“。
操作符具有优先级,但建议使用括号明确规定计算顺序。
public static void main(String[] args) {
int a = 1;
int b = 2;
String str = "123";
//当一个String类型后紧跟一个非String类型,系统会尝试将非String类型转为String类型
System.out.println(a + b);
System.out.println(a + b + str);
System.out.println(a + str + b);
}
赋值使用操作符”=“。将右值赋给左值,右值可以为任意常数、变量、表达式(能生成值),左值必须为已命名的变量(已声明为final类型的在某些情况下不行)。
基本类型的赋值是直接赋值,对象的赋值只是赋值了引用。对于方法中传参也符合这个规则,当然 String 是个特例,你可以把它看成是 char 的包装类就容易理解了。
public static void main(String[] args) {
int a = 1;
int b = 2;
System.out.println("a=" + a + ";b=" + b);
a = b;
System.out.println("将b的值赋给a后,a=" + a + ";b=" + b);
a = 3;
System.out.println("修改赋值后的a,b值并未受影响,a=" + a + ";b=" + b);
Person person1 = new Person(1);
Person person2 = new Person(10);
System.out.println("person1=" + person1.toString() + ";person2=" + person2);
//将person2赋值给person1,person1的之前的引用不再被引用,过一段时间就会被垃圾回收器回收
person1 = person2;
System.out.println("将person2的引用赋值给person1,person1=" + person1.toString() + ";person2=" + person2);
//修改person1的数据将影响person2,因为两者的引用指向同一个对象
person1.setAge(100);
System.out.println("修改person1的age将影响person2的age,person1=" + person1.toString() + ";person2=" + person2);
}
public static class Person {
private int age;
public Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
输出如下:
a=1;b=2
将b的值赋给a后,a=2;b=2
修改赋值后的a,b值并未受影响,a=3;b=2
person1=Person{age=1};person2=Person{age=10}
将person2的引用赋值给person1,person1=Person{age=10};person2=Person{age=10}
修改person1的age将影响person2的age,person1=Person{age=100};person2=Person{age=100}
++:称为自动递增操作符
--:称为自动递减操作符
++i称为前缀式,i++称为后缀式。前缀式先生成值再运算,后缀式先运算再生成值。
">"、"<"、">="、"<="、"=="、"!="是关系操作符。表达式为真则返回true,为假返回false。
其中 boolean 类型只适用"=="和"!="。
补充:”==“和”!=“用于比较对象的引用是否相等。重写 Object 类的 equals()
方法即可比较对象的值是否相等,但是 equals()
方法默认也是比较对象的引用。
逻辑操作符
”与(&&)“、”或(||)“、”非(!)“根据参数的逻辑关系生成一个布尔值。且只能应用于布尔值的表达式。”与(&&)“和”或(||)“具有”短路“现象。一旦能准确无误的判断表达式的值,就不再计算余下部分。
直接常量
L(l):long
F(f):float
D(d):double
0x(0X):十六进制,0-9、a-f
0:八进制,0-7
在 Java 中,可以调用 Integer 或者 Long 中相应的方法,将十进制数转化为二进制、八进制或者十六进制。
public static void main(String[] args) {
int a = 16;
//二进制
System.out.println("Binary="+Integer.toBinaryString(a));
//八进制
System.out.println("Octal="+Integer.toOctalString(a));
//十六进制
System.out.println("Hex="+Integer.toHexString(a));
}
位运算符
位运算符有如下几种:
- 按位与”&“:只有对应的两个二进位均为1时,结果位才为1 ,否则为0。1&1=1,1&0=0,0&1=0,0&0=0
- 按位或”|“:只要对应的二个二进位有一个为1时,结果位就为1。1&1=1,1&0=1,0&1=1,0&0=0
- 按位异或”“:参与运算的两个值,如果两个相应位相同,则结果为0,否则为1。00=0,10=1,01=1,1^1=0。按位异或可以实现两个数的交换,而不必借助临时变量。
- 取反”“:1=0,~0=1
- 左移”<<“:地位插入0。
- 右移”>>“:若符号为正,则高位插入0;若符号为负,则高位插入1。
- 无符号右移“>>>”:无论正负,都在高位插入0。
以上为操作符,除按位异或“^”外,其余都可与“=”连用。
验证按位异或”^“可以实现两个数的交换:
public static void main(String[] args) {
int a = 16;
int b = 10;
System.out.println("异或前,Binary,a=" + Integer.toBinaryString(a) + ";b=" + Integer.toBinaryString(b));
a = a ^ b;
b = b ^ a;
a = a ^ b;
System.out.println("异或后,Binary,a=" + Integer.toBinaryString(a) + ";b=" + Integer.toBinaryString(b));
}
输出如下:
异或前,Binary,a=10000;b=1010
异或后,Binary,a=1010;b=10000
这里我们来验证下异或运算的效率如何。
public static final int TIMES = 1000000000;
public static void main(String[] args) {
exchange1();
exchange2();
}
private static void exchange1() {
long start = System.currentTimeMillis();
int a = 16;
int b = 10;
for (int i = 0; i < TIMES; i++) {
a = a ^ b;
b = b ^ a;
a = a ^ b;
}
System.out.println("执行" + TIMES + "次异或操作交换数据要" + (System.currentTimeMillis() - start) + "ms");
}
private static void exchange2() {
long start = System.currentTimeMillis();
int a = 16;
int b = 10;
int temp;
for (int i = 0; i < TIMES; i++) {
temp = a ;
a = b;
b = temp;
}
System.out.println("执行" + TIMES + "次使用临时变量交换数据要" + (System.currentTimeMillis() - start) + "ms");
}
输出如下:
执行1000000000次异或操作交换数据要1820ms
执行1000000000次使用临时变量交换数据要4ms
发现使用异或操作实现值得交换竟然没有使用临时变量来的高效。
三元操作符
三元操作符的表达式形如:
//若布尔表达式为真,则计算value1
//否则,计算value2
boolean-exp ? value1 : value2
类型转换
在 Java 中,基本类型的转换有两种方式:
- 扩展转换:低精度类型转换成高精度类型,编译器会自动执行,不需要显示申明。如,将 int 转换为 long 类型
- 窄化转换:将高精度类型转换为低精度类型,需要显示申明,因为窄化转换会丢失数据。如,将 long 转换为 int 类型。
Java 中的基本数据类型除 boolean 类型外,都允许类型转换。类也能实现转换,但仅限于同一类。
截尾和舍入
Java 中将浮点数转换为 int 或 long ,执行的是截尾操作。如需进行舍入操作,则需要使用 Math.round()
方法。
public static void main(String[] args) {
float a = 1.6f;
System.out.println("(int)a=" + (int) a);
System.out.println("Math.round(a)=" + Math.round(a));
}
输出如下:
(int)a=1
Math.round(a)=2
以上就是《Java 编程思想》操作符这一章节的读书笔记~