3.2 使用Java操作符
几乎所有的操作符都只能操作“基本类型”。例外的操作符是“=”、“==”,这些操作符能操作所有的对象。除此以外,String类支持“+”和“+=”。
3.5 算术操作符
下面这个例子展示了Random的用法:
public class MathOps {
Random rand=new Random(47);
int j;
j=rand.nextInt(100)+1;
print("j:"+ j );
}
要生成数字,程序首先会创建一个Random类的对象。如果在创建过程中没有传递任何参数,那么Java就会将当前时间作为随机数生成器的种子,并由此在程序每一次执行时都产生不同的输出。
通过Random类的对象,程序可生成许多不同类型的随机数字。做法很简单,只需调用方法nextInt()和nextFloat()即可(也可以调用nextLong()或者nextDouble())。传递给nextInt的参数设置了所产生的随机数的上限,而其下限为0,但是这个下限并不是我们想要的,因为它会产生除0的可能性,因此我们对结果做了加1操作。
3.6 自动递增和递减
类似地,“前缀递减”意味着“–”操作符位于变量或表达式地前面;而“后缀递减”意味着“–”操作符位于变量或表达式的后面。对于前缀递增和前缀递减(如++a或 --a),会先执行运算,再生成值。而对于后缀递增和后缀递减(如a++ 或a–),会先生成值,再执行运算。下面是一个例子
public class AutoInc{
public staic 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 关系操作符
3.7.1 测试对象的等价性
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.ptintln(n1 != n2);
}
}/* Output:
false
true
*/
尽管对象的内容相同,然而对象的引用却是不同的,而==和!=比较的就是对象的引用。
如果想比较两个对象的实际内容是否相同,又该如何操作?此时,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“基本类型”,基本类型直接使用==和!=即可。
但事情不总是这么简单!假设你创建了自己的类,就像下面这样:
class Value{
int i;
}
public class EqualMethods{
public static void main(String[] args){
Value v1 = new Value();
Value v2 = new Value();
v1.i = v2.i = 100;
System.ou.println(v1.equals(v2));
}
}/*Output:
false
*/
结果又是false!这是由于equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。
大多数Java类库都实现了equals()方法,以便用来比较对象的内容,而非比较对象的引用。
3.9 直接常量
一般说来,如果在程序使用了“直接变量”,编译器可以准确地要知道生成什么样的类型,但有时候却是模棱两可的。如果发生这种情况,必须对编译器加以适当的“指导”,用与直接量相关的某些字符来额外增加一些信息。
直接常量后面的后缀字符标志了它的类型。若为大写(或小写)的L,代表long(但是,使用小写字母容易造成混淆,因为它看起来很像数字1)。大写(或小写)字母D,则代表double。
十六进制适用于所有整数数据类型,以前0x(或0X),后面跟随0-9或小写(或大写)的a-f来表示。
3.9.1 指数计数法
Java采用了一种很不直观的计数法来表示指数。例如:
public class Exponents{
public static void main(String[] args){
float expFloat = 1.39e-43f;
System.out.println(expFloat);
double expDouble = 47e47d;
double expDouble = 47e47; // Automatically double
System.out.println(expDouble);
}
}/* Output:
1.39E-43
4.7E48
*/
在科学与工程领域,“e"代表自然对数的基数,约等于2.718。然而,设计FORTRAN语言的时候,设计师们很自然地决定e代表”10地幂次“。这种做法很奇怪,因为FORTRAN最初是面向科学与工程设计领域地,它的设计者们对引入这样容易令人混淆的概念应该很敏感才对。但不管怎样,这种惯例在C、C++以及Java中被保留了下来。所以倘若习惯将e作为自然对数的基数使用,那么在Java中看到像1.39e-43f这样的表达式时,请转换思维,它真正的含义是1.39*10-43。
3.10 按位操作符
按位操作符来操作整数基本数据类型的单个”比特“(bit),即二进制位。按位操作符会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。
按位操作符来源于C语言面向底层的操作,在这种操作中经常需要直接操纵用硬件,设置硬件寄存器内的二进制位。Java的设计初衷是嵌入电视机机顶盒内,所以这种面向底层的操作仍然被保留了下来。但是,人们不会过多地用到位操作符。
”与“操作符(&),”或“操作符(|)。
如果输入位地某一个是1,但不全是1,那么按位”异或“操作(^)生成一个输出位1。按位”非“(~),也称作取反操作符,它属于一元操作符,只对一个操作数进行操作(其他按位操作符是二元操作符)。
按位操作符可与等号(=)联合使用,以便合并运算和赋值:&=、|=和^=都是合法地(由于”~"是一元操作符,所以不可与“=”联合使用)。
3.11 移位操作符
移位操作符地运算对象也是二进制的“位”。移位操作符只可用来处理整数来行。左移位操作符(<<)能够按照操作符右侧指定的位数将操作符左边的操作数向左移动(在低位补0)。“有符号”右移位操作符(>>)则按照操作符右侧指定的位数将操作符左边的操作数向右移动。“有符号” 右移位操作符使用 “符号扩展”:若符号为正,则在高位插入0;若符号为负,则在高位插入1。Java中还增加了一种“无符号”右移操作符(>>>),它使用“零扩展”:无论正负,都在高位插入0。这一操作符是C或C++中所没有的。
如果对char、byte或者short类型的数值进行移位处理,那么在移位之前,它们会被转换位int类型,并且得到的结果也是一个int类型的值。
3.12 三元操作符 if-else
三元操作符也称为条件操作符,它显得比较特别。其表达式采取下述形式:
boolean-exp ? value0 : value1
如果boolean-exp(布尔表达式)的结果为true,计算value0。如果boolean-exp的结果为false,就计算value1。
3.15 类型转换操作符
3.15.1 截尾和舍入
在将float或double转型为整型值时,总是对该数字执行截尾。如果想要得到舍入的结果,就必须使用java.lang.Math中的round()方法。
3.16 Java没有sizeof
在C和C++中,sizeof()操作符可以告诉你为数据项分配的字节数。在C和C++中,需要使用sizeof()的最大原因是为“移植”。不同的数据类型在不同的机器上可能有不同的大小,所以在进行一些与存储空间有关的运算时,程序员必须获悉那些类型具体有多大。例如,一台计算机可用32位来保存整数,而另一台只用16位保存。显然,在第一台机器中,程序可保存更大的值。可以想象,移植是令C和C++程序员颇为头疼的一个问题。
Java不需要sizeof()操作符来满足这方面的需要,因为所有数据类型在所有机器中的大小都是相同的。
3.17 操作符小节
在char、byte和short中,我们可看到使用算术操作符中数据类型提升的效果。对这些类型的任何一个进行算术运算,都会获得一个int结果,必须将其显式地类型转换回原来地类型(窄化转换可能会造成信息地丢失),以将值赋给原本的类型。但对于int值,却不必进行类型转化,因为所有数据都已经属于int类型。但是不要放松警惕,认为一切事情都是安全的,如果对两个足够大的int值执行乘法运算,结果就会溢出。