Java编程思想(三、操作符)
操作符是接收一个或多个参数,并生成一个新值。参数的形式与普通的方法调用不同,但效果是相同的。
1、基本类型存储了实际的数值。而并非指向一个对象的引用。所以在为其赋值的时候,是直接把一个地方的内容复制到了另一个地方。例如,对基本数据类型使用a=b,那么b的内容就复制给了a。若接着修改了a,而b根本不会受这种修改的影响。(在上一篇java编程思想(2)中,我们就知道基本类型是存储在堆栈中的。假设a=4,那么堆栈中如果没有4,则会开辟一个空间,使值为4。a=b之后,b也指向了堆栈中的这个4。此时a再等于5。那么会重新在堆栈中寻找5,若没有则新开辟使之为5,然后a指向5。故不会影响b)
但是在为对象“赋值”的时候,情况会发生变化。首先我们知道,对对象的操作,我们真正操作的是对对象的引用。所以倘若"将一个对象赋值给另一个对象",实际上是将“引用”从一个地方复制到另一个地方。这意味着如果对对象使用c=d之后,那么c和d都将指向原来只有d指向的那个对象(两个遥控器(引用)都能操作按个电视机(对象)了)。
2、别名。
Tank tank1 = new Tank(); Tank tank2 = new Tank(); tank2=tank1;
当这个时候,tank2与tank1实际上是一个引用了,都指向了tank1。此时,tank2也可以说是tank1的一个别名了。而刚开始tank2指向的那个对象将因为没有引用指向它了,而被“垃圾回收器”自动清理。
在方法的调用中,也是存在别名问题的。
void F(Tank tank); F(tank1);//并不是说讲tank1指向的对象赋值给tank形参。F()所做的事情,会直接改变tank1所指向的对象。F(Tank tank)里面传递的实际上是一个引用。
3、Java操作符。加号与一元的正号(+)、减号与一元的负号(-)、乘号(*)、除号(/)以及赋值号(=)。 “=”、“==”、“!=”这三个操作符能操作所有的对象。此外,String类支持“+”和“+=”。
优先级。操作符的优先级决定了各部分的计算顺序。
赋值。赋值使用操作符“=”。取右边的值复制给左边。
算数操作符。要生成数字,程序首先会创建一个Random类的对象。如果在创建过程中没有传递任何参数。那么Java就会将当前时间作为随机数生成器的种子,并由此在程序每一次执行时都产生不同的输出。(随机数生成器对于特定的种子值总是产生相同的随机数序列)。
一元减号(-)和一元加号(+)与二元减号和加号都是使用相同的符号。根据表达式的书写形式,编译器会自动判断出使用的是哪一种。例如 x= -a; x=a * -b 编译器都能正确识别。但是有时读者会不清除,所以有时候更明确地写成 x= a * (-b)。 一元减号用于转变数据的符号,而一元加号只是为了与一元减号相对应,但是它唯一的作用是将较小类型的操作数提升为int。
4、自动递增和递减。递增与递减是两种相当不错的快捷运算,递减操作是“--”,意为“减少一个单位”;递增操作符是“++”,意为“增加一个单位”。++a 就等于(a=a+1)。
这两种操作符各有两种使用方式,通常称为“前缀式”和“后缀式”。“前缀递增”表示“++”操作符位于变量或表达式的前面;而“后缀递增”表示“++”操作符位于变量或表达式的后面。前缀式,会先执行运算再生成值。后缀式,则是先生成值再进行运算。
5、关系操作符。关系操作符是生成的是一个boolean(布尔)结果,它们计算的是操作数的值之间的关系。如果关系是真实的,关系表达式会生成true(真);如果不真实,关系表达式会生成false(假)。关系操作符包括小于(<)、大于(>)、小于或等于(<=)、大于或等于(>=)、等于(==)以及不等于(!=)。等于与不等于适用于所有的基本数据类型,而其他比较符不适用于boolean类型。因为boolean值只能为true或false,“大于”和“小于”没有实际意义。
对于对象的比较。“==”与“!=”比较的是对象的引用。如果想比较对象的实际内容,则是使用 equals()。但equals()不适用与基本类型。基本类型,直接使用“==”和“!=”即可。
但equals()的默认行为是比较引用。所以除非在自己的新类中覆盖equals()方法,否则不可能表现出我们希望的行为。大多数的java类库都实现了equals()方法,以便来比较对象的内容,而非比较对象的引用。
6、逻辑操作符。逻辑操作符有“与”(&&)、"或"(||)、“非”(!)能根据参数的逻辑关系,生成一个布尔值(true或false)。逻辑操作符只可用于布尔值。
短路。当使用逻辑操作符时,我们会遇到一种“短路”现象。即一旦能够明确无误地确定整个表达式的值,就不必再计算表达式的余下部分了。很简单,假设 真||假||真||假。 运算到真的时候,因为是或运算,所以无论后面跟什么值,这个整个的算式一定为真,故不必再计算剩下的值了。
7、直接常量。使用直接常量时,编译器可以准确地知道要生成什么样的类型(比如 int i=0x2f)。但有时是模棱两可的,则需要在直接常量后面增加某些字符来额外增加一些信息。比如大写(或小写)的L,代表long(但是,使用小写字母l容易造成混淆,因为它看来很像数字1)。大写(或小写)的F,代表float;大写(或小写)字母D,则代表double。十六进制数适用于所有整数类型,以前缀0x,后面跟随0-9或小写(或大写)的a-f来表示。八进制由前缀0以及后续的0-7的数字来表示。
8、指数记数法。由e来表示10的幂次。
9、按位操作符。按位操作符用来操作整数基本数据类型中的单个“比特”(bit),即二进制位。按位操作符会对两个参数中对应的位执行布尔代数运算,并最终生成一个结果。
按位“与” & :如果两个输入位都是1 则输出1,否则输出0;
按位“或” | :两个输入位中只要有一个1,则就将输出1;
按位“异或” ^:如果输入位的某一个是1,但不全是1,则将输出1;
按位“非” ~:也是取反操作符。这个属于一元操作符。只对一个数进行操作(其他操作符都是二元操作符)。按位“非”生成与输入位相反的值——若输入0,则输出1;若输入1,则输出0。
按位操作符可与等号(=)联合使用,以便合并运算和赋值:&=、|=和^=都是合法的(由于~是一元操作符,所以不可与“=”联合使用)。
布尔类型作为一种单比特值对待,多少有点独特。可对它执行按位“与”、“或”、“异或”。但是不能按位“非”,可能是为了避免与逻辑NOT混淆。
10、移位操作符。移位操作符的对象也是二进制的“位”。移位操作符只可用来处理整数类型(基本类型的一种)。左移位操作符(<<)能按照操作符右侧指定的位数将操作符左边的操作数向左移动(在低位补0)。“有符号”右移位操作符(>>)能按照操作符右侧指定的位数将操作符左边的操作数向右移动。
11、三元操作符 if-else。三元操作符,也称为是条件操作符。 boolean-exp ? value0:value1。如果布尔表达式结果为true则取value0,布尔表达式结果为false则取value1。条件操作符与if-else普通语句完全不同,因为条件操作符会产生一个值。
12、字符串操作符+和+=。在java中,程序员并不能重载操作符。但字符串操作符有一些很有趣的行为,如果表达式以一个字符串起头,那么后续所有操作数都必须是字符串类型。(编译器会把双引号内的字符序列自动转成字符串)。
13、类型转换操作符。在适当的时候,Java会将一种数据类型自动转换成另一种。假设我们为某一浮点变量赋以一个整数值,那么编译器会将int自动转换成float。类型转换运算允许我们显式地进行这种类型的转换,或者在不能自动转换的时候强制进行类型转换。在java中,类型转换是一个比较安全的操作,但如果要执行一种窄化转换的操作,编译器会强制我们进行类型转换(因为窄化转换会面临信息丢失的危险,如果无论如何要这么做,必须显式地进行类型转换(即开发人员知道自己在做这个窄化转换))。
14、提升。如果对基本数据类型执行算数运算或按位运算,只要类型比int小(即char、byte或者short),那么在运算之前,这些值会自动转化成int。这样一来,最终生成的结果就是int类型。如果想把结果赋值给较小的类型,就必须使用类型转化。通常,表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。如果将一个float值与一个double值相乘,结果就是double,如果将一个int和一个long值相加,则结果为long。
而且,在java中没有sizeof。所有的数据类型在所有机器中的大小都是相同的。