Chapter 3 - Operators
第三章:
-
运算符计算优先级,先乘除后加减,有括号先计算括号内的
-
十六进制以OX开头,八进制以0开头,记住。
-
整数除法会直接去掉结果的小数位,而不是四舍五入地圆整结果。
-
Random随机数生成器对于特定的种子值总是产生相同的随机数序列,传递给nextInt()的参数设置了所产生的随机数的上限,而起下限为0。
-
equals()的默认行为是比较引用,所以除非在自己的新类中覆盖该方法,否则无法比较对象内的值。
-
如果在应该使用String值的地方使用了布尔值,布尔值会自动转换成适当的文本形式
-
编译器通常会将指数作为双精度数(double)处理,没有F,就会受到一条出错提示。如下:
float f4 = 1.39e-43f 含义 1.39*10的负43次方。
8.二进制和十六进制或者八进制都是数数字的个数,有几位便是几进制的几次方,比如:
1111(2进制) = 共有四位,第一个1就是2的3次方+2的2次方+2的一次方+1 = 15
OXFFFF(16进制ox开头) = 共有四位,第一个F就是15个16的3次方+15个16的2次方+15个16的一次方+15
0177(8进制0开头) = 共有三位,第一个1就是8的2次方+7个8的1次方+7
按位操作符:
因为java中的所有数值类型都有正负号,所以不要去寻找无符号的数据类型。
int 32位,正负表示方法 用字节的最高位表示:"1"表示"正","0"表示"负"
byte 8位:
1(负)0000000
0(正)1111111
由于Byte=8bit,最大表示范围为-128~127
127=01111111, -128 10000000
取负数的二进制方法:
在计算机系统中,数值一律用补码来表示(存储),主要原因:使用补码,可以将符号位和其它位统一处理;
同时,减法也可按加法来处理(5-2 == 5+(-2))。另外,两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。补码与原码的转换过程几乎是相同的。
例如:
数值的补码表示也分两种情况:
(1)正数的补码:与原码相同。
(2)负数的补码:符号位为1,其余位为该数绝对值的原码按位取反;然后整个数加1
18:
2进制:00000000000000000000000000010010
15:
2进制:00000000000000000000000000001111
-15补码计算:
00000000000000000000000000001111
11111111111111111111111111110001
补码与原码的转换过程几乎是相同的
11111111111111111111111111110001
00000000000000000000000000001111
15按位~(非) ~:1输出0,0输出1, 如下:
00000000000000000000000000001111
——————————————————————
11111111111111111111111111110000 十进制数为-16
18和15 按位& &:两个都是1才是1,否则是0, 如下:
00000000000000000000000000010010
00000000000000000000000000001111
——————————————————————
00000000000000000000000000000010 十进制数为2
8和15 按位| |:两个都是0才是0,否则都是1, 如下:
00000000000000000000000000010010
00000000000000000000000000001111
——————————————————————
00000000000000000000000000011111 十进制数为31
8和15 按位^ ^:某一个是1,但不全是1,才输出1, 如下:
00000000000000000000000000010010
00000000000000000000000000001111
——————————————————————
00000000000000000000000000011101 十进制数为29
移位操作符:
15:
2进制:00000000000000000000000000001111
左移位 15<<5
00000000000000000000000000001111
——————————————————————
00000000000000000000000111100000 十进制数为480
带符号右移位 15>>2,因为15为正数,所以高位补0
00000000000000000000000000001111
——————————————————————
00000000000000000000000000000011 十进制数为3
带符号右移位 -15>>2,因为15为负数,所以高位补1
00000000000000000000000000001111
——————————————————————
11111111111111111111111111110001 负数形式
——————————————————————
11111111111111111111111111111100 十进制数为-4
无符号右移位 15>>>2,不管符号,都在高位补0
15>>>2:
00000000000000000000000000001111
——————————————————————
00000000000000000000000000000011 十进制数为3
-15>>>2:
00000000000000000000000000001111
——————————————————————
11111111111111111111111111110001 负数形式
——————————————————————
00111111111111111111111111111100 十进制数位1073741820
char ,byte, short 的数值进行移位处理时,在移位进行之前,会被转化为int,移位操作符用于整形,
移位可与等号(<<=,>>=,>>>=)组合使用,特别注意:《只有右端的低5位才有用》
这是说y向右移(左移)n位,n的值只有右端的低5位才有用(因为int只有32位)。即
执行语句 y>> 34 对y右移34位时,先把34化成二进制:100010,对该二进制数取右边5位(因为超过5位就变成了移动32位以上了,而int一个就有32个位数),即00010(把第一个去掉),化成十进制数为2,
所以实际上是对i右移两位:
15>>2 = 3 同 15>>34 = 3
在进行无符号右移位结合赋值操作时,可能会遇到一个问题:如果对byte或short值进行这样的移位运算,得到的值可能不是正确的结果,为什么没有char是因为char不能赋值为负数,所以默认是无符号的移位。但是对byte或short负数进行无符号移位时就有可能有问题,得到的仍然是负数, URShift
short s = -1;
println(Integer.toBinaryString(s)); //output: 11111111111111111111111111111111
s >>>= 10; // 00000000001111111111111111111111 但是复制给short马上截断
println(Integer.toBinaryString(s)); // 1111111111111111 short最大保留16位 即-1
如果对基本数据类型执行算数运算或按位运算(任何运算),大家会发现,只要类型比int小,那么在运行算之前,这些值自动转换成int.最终的结果就是int型,
如果想把结果赋值给较小的类型,就必须使用类型转换。如下:
void charTest(char x, char y) {
x = (char)(x + y);
}
不需要类型转换:
x += y;
在java中 short s1 = 1; s1 = s1 + 1; 有什么错 ?
答:当然有错误,short占2个字节,而常量1是int占4个字节,short型变量+上int型值计算结果是int型,占4个字节,然后付给一个short型变量s1,就要丢失2个字节的精度,这是不容许的。你非要这么做的话,我给你提供一个办法:s1=s1+1;改成s1+=1;虽然是一个意思,但是在jvm里面是不同的方法做的,是运算符重载,所以是不一样的。
基本类型能做的运算:
布尔值,我们只能赋予它true和false值不能对布尔值相加,或对布尔值进行其他任何运算(除了按位与,按位或,按位异或)
char,short,byte我们不能对着三种类型进行布尔值转换,转为其他类型都可以,但是这三个其中任何一个在进行任何一个算术运算时,都会被提升为int,必须显示类型转换。
浮点数无法进行按位运算,布尔值转换,再将float或double转型为整型值时,总是对该数字执行截尾,如果想得到舍入的结果,就需要用到java.lang.math中的round()方法
对于布尔值,按位操作符具有与逻辑操作符相同的效果,只是他们不会中途“短路”。此外,针对布尔值进行的按位运算为我们新增了一个“异或”逻辑操作符
boolean x = false;
boolean y = true;
System.out.println(x & y); false
System.out.println(x | y); true
System.out.println(x ^ y); true
在调用构造函数之前,java编译器会自动把block中的代码复制到构造函数里,而且是置于构造函数代码的前面。然后,静态block的优先级当然是高于普通block,因为静态字段是在所有实例化之前完成的动作。
赋值操作
因为java基本型存在stack中,储存的是实际的值,而不是引用。因此,如果操作符赋值基本数据类型a=b,是直接把b的值复制到了a,就是所谓的“传值”。接下来修改a,不会对b有影响。
int b=5;
int a;
a=b
但当a和b不是基本型,而是对象的时候,再进行a=b的赋值操作,就只是把b对对象的引用复制一份给a。这时,a和b指向同一个对象,改变其中任意一个,一会改变另一个。这就是所谓的“传址”。也叫别名问题。
String a="boy";
String b="girl";
a=b; //此时,a,b都指向"girl"
a="boy"; //此时,a,b都指向"boy"
将一个对象传递给方法时,也会产生“别名问题”,也就是也是“传址”。下面练习3中的forceToChangeTo5方法是个很好的例子。对象toto作为参数,传递了自己的地址进去,而不是自己的一份拷贝。