《Java编程思想》第3章 操作符

源码地址:https://github.com/yangxian1229/ThinkingInJava

3.1 更简单的打印语句

import static net.mindview.util.Print.*;

3.2 使用Java操作符

+,-,*,/,=的用法和其他编程语言类似。
几乎所有的操作符都只能操作“基本类型”。例外的操作符是“=”、“==”和“!=”,这些操作符能操作所有的对象。除此之外,String类支持“+”和“+=”。

3.3 优先级

3.4 赋值

“=”
常数不能作为左值(比如说不能4=a;)
基本类型存储了实际的数值,而并非指向一个对象的引用,所以在为其赋值的时候,是直接将一个地方的内容复制到了另一个地方。
对一个对象进行操作时,我们真正操作的是对对象的引用。所以倘若“将一个对象赋值给另一个对象”,实际是将“引用”从一个地方复制到另一个地方。

//: ch3/Assignment.java
// Assignment with objects is a bit tricky.
package ch3;
import static net.mindview.util.Print.*;
import java.nio.file.ProviderNotFoundException;
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("1: t1.level:"+t1.level+", t2.level:"+t2.level);
		t1 = t2;//不再被引用的的对象由“垃圾回收器”自动清理
		print("2: t1.level:"+t1.level+", t2.level:"+t2.level);
		t1.level = 27;
		print("3: t1.level:"+t1.level+", t2.level:"+t2.level);
	}
}/* Output:
1: t1.level:9, t2.level:47
2: t1.level:47, t2.level:47
3: t1.level:27, t2.level:27
*///:~

别名现象,可以用下面方法避免:
t1.level = t2.level;
这样就是可以保持两个对象独立,而不是将t1和t2绑定到相同的对象。

3.5 算术操作符

加号(+)、减号(-),除号(/)、乘号(*)以及取模操作符(%)。整数除法会直接去掉结果的小数位,而不是四舍五入地园整结果。
创建Random对象时提供种子(用于随机数生成器的初始化值,随机数生成器对于特定的种子值总是产生相同的随机序列。如果在创建过程中没有传递任何参数那么Java就会将当前时间作为随机数生成器的种子,并由此在程序每一次执行时都产生不同输出。)
通过Random类的对象,程序可以生成许多不同类型的随机数字。做法很简单,只需调用方法**nextInt()nextFloat()**即可(nextLong()nextDouble())。

3.5.1 一元加、减操作符

一元减号用于转变数据的符号。而一元加号只是为了与一元减号相对应,但是它唯一的作用仅仅是将较小类型的操作数提升为int

3.6 自动增和递减

对于前缀递增和前缀递减(如++a或–a),会先执行运算,再生成值。而对于后缀递增和后缀递减(如a++或a–),会先生成值,再执行运算。

//: ch3/AutoInc.java
// Demonstrates the ++ and -- operators.
package ch3;
import static net.mindview.util.Print.*;
public class AutoInc {
	public static void main(String[] args) {
		int i = 1;
		print("i = "+i);
		print("++i = "+ ++i);
		print("i++ = "+ i++);
		print("i = "+i);
		print("--i = "+ --i);
		print("i-- = "+i--);
		print("i = "+i);
	}
}/* Output:
i = 1
++i = 2
i++ = 2
i = 3
--i = 2
i-- = 2
i = 1
*///:~

3.7 关系操作符

关系操作符生成的是一个boolean结果。
<,>,<=,>=,==,!=
等于和不等于适用于所有的基本数据类型,而其他比较符不适用于boolean类型。因为boolean值只能为truefalse,“大于”和“小于”没有实际意义。

3.7.1 测试对象的等价性

==和!=比较的就是对象的引用。

想要比较两个对象,使用equals()。但这个方法不适用于“基本类型”,基本类型直接使用==和!=

//: ch3/Equivalence
package ch3;
class Value{
	int i;
}
public class Equivalence {
	public static void main(String[] args) {
		Integer n1 = new Integer(47);
		Integer n2 = new Integer(47);
		System.out.println(n1 == n2);
		System.out.println(n1 != n2);
		System.out.println(n1.equals(n2));
		
		Value v1 = new Value();
		Value v2 = new Value();
		v1.i = v2.i = 100;
		System.out.println(v1.equals(v2));
	}
}/* Output:
false
true
true
false
*///:~

equals()的默认行为是比较引用。在自己的新类中应该覆盖equals()方法。

3.8 逻辑操作符

逻辑操作符 与(&&),或(||),非(!)能根据参数的逻辑关系,生成一个boolean值(truefalse)。
注意:如果在应该使用String值的地方使用了布尔值,布尔值会自动转换成适当的文本形式。

3.8.1 短路

当使用逻辑操作符时,我们会遇到一种“短路”现象。即一旦能够明确无误地确定整个表达式的值,就不再计算表达式余下部分了。事实上,如果所有的逻辑表达式都有一部分不必计算,那将获得潜在的性能提升。

3.9 直接常量

直接常量后面的后缀字符标志了它的类型,若为大写(或小写)的L,代表long。大写(或小写)字母F,代表float。大写(或小写)D,代表double
十六进制适用于所有整数数据类型,以前缀0x(或0X),后面跟随0-9或小写(或大写)的a-f来表示。
八进制由前缀0以及后续的0~7的数字来表示。
在使用十六进制或八进制记数法时,以二进制形式显示结果将非常有用。通过使用IntegerLong类的静态方法toBinaryString()很容易地实现这一点。请注意,如果将比较小的类型传递给Integer.toBinaryStirng()方法,则该类型自动被转换为int。

3.9.1 指数记数法

e

3.10 按位操作符

与&,或|,非~,异或^
$=,|=,^=
我们将布尔类型作为一种单比特对待。我们可以对它执行按位“与”、“或”、“异或”运算,但不能执行按位“非”。

3.11 移位操作符

移位操作符的运算对象也是二进制的“位”。移位操作符只可用来处理整数类型。左移位操作符(<<)能按照操作符右侧指定的位数将操作符左边的操作数向左移动(在低位补0)。“有符号”右移操作符(>>)则按照操作符右侧指定的位数将操作符左边的操作数向右移动。“有符号”右移操作符使用“符号扩展”:若符号为正,则在高位插入0;若符号为负,则在高位插入1。Java中添加了一种“无符号”右移位操作符(>>>),它使用“零扩展”:无论正负,都在高位插入0.
如果对charbyte或者short类型的数值进行移位处理,那么在移位进行之前,它们会被转换为int类型,并且得到的结果也是一个int类型的值。
“移位”可与“等号”(<<=或>>=或>>>=)组合使用。

3.12 三元操作符if-else

boolean-exp ? value0 : value1

3.13 字符串操作符+和+=

字符串操作符有一些很有趣的行为。如果表达式以一个字符串起头,那么后续所有操作数都必须是字符串型(请记住,编译器会把双引号内的字符序列自动转成字符串);

package ch3;
import static net.mindview.util.Print.*;
public class StringOprators {
	public static void main(String[] args) {
		int x=0,y=1,z=2;
		String s = "x,y,z ";
		print(s+x+y+z);
		print(x+" "+s);//Converts to a String
		s += "(summed) = ";
		print(s + (x+y+z));
		print(""+x);//Shorthand for Integer.toString()
	}
}/* Output:
x,y,z 012
0 x,y,z 
x,y,z (summed) = 3
0
*/

3.14 使用操作符时常犯的错误

=,==,的误用

3.15 类型转换操作符

int i = 200; long lng = (long) i; long lng2 = (long)200;
既可对数值进行类型转换,也可对变量进行类型转换。
在Java中,类型转换是一种比较安全的操作。然后,如果要执行一种名为窄化转换(narrowing conversion)的操作(也就是说,将能容纳更多信息的数据类型转换为无法容纳那么多信息的类型),就有可能面临信息丢失的危险。此时编译器会强制我们进行类型转换。而对于扩展转换(widening conversion),则不必显式地进行类型转换,因为新类型肯定能容纳原来类型的信息,不会造成任何信息的丢失。
Java允许我们把任何基本数据类型转换成别的基本数据类型,但布尔型除外,后者根本不允许进行任何类型的转换处理。

3.15.1 截尾和舎入

package ch3;
import static net.mindview.util.Print.*;
public class CastingRounding {

	public static void main(String[] args) {
		double above = 0.7,below = 0.4;
		float fabove = 0.7f,fbelow = 0.4f;
		print("(int)above:"+(int)above);
		print("(int)below:"+(int)below);
		print("(int)fabove:"+(int)fabove);
		print("(int)fbelow:"+(int)fbelow);
		
		print("Math.round(above):"+Math.round(above));
		print("Math.round(below):"+Math.round(below));
		print("Math.round(fabove):"+Math.round(fabove));
		print("Math.round(fbelow):"+Math.round(fbelow));
	}
}/* Output:
(int)above:0
(int)below:0
(int)fabove:0
(int)fbelow:0
Math.round(above):1
Math.round(below):0
Math.round(fabove):1
Math.round(fbelow):0
*///:~

3.16 Java没有sizeof

不需要,因为所有的数据类型在所有机器中大小是相同的。

猜你喜欢

转载自blog.csdn.net/lanzijingshizi/article/details/83963063
今日推荐