第四章 运算符
在最底层,Java中的数据是通过使用操作符来操作的。操作符接受一个或多个参数,生成一个新值。操作符作用于操作数,生成一个新值,或者改变此操作数的值。几乎所有的操作符都只能操作“基本类型”。例外的操作符是“=”、“==”和“!=”,这些操作符能操作所有对象。String类支持“+”和“+=”。
优先级。最基础的,先乘除,后加减,有括号先算括号里面的。
赋值使用操作符“=”,意思是取右值赋值给左值,常数不能作为左值。
“==”和“!=”比较的是对象的引用(对象在内存中的首地址),判断是否为同一个对象。equals()比较的是对象的内容,但是equals()不适用于基本类型,基本类型直接使用“==”和“!=”即可。还需要注意一点,equals()方法,默认行为是比较引用的,只有重写equals()方法,才能让它比较对象的内容。对于基本类型的包装类和字符串(String),已经重写了equals()方法,使其比较的是值。
对于 Integer 和 Long 类型,在比较数值是否相等时,我们需要了解以下知识,否则很容易犯错。基本类型的数值型是可以直接使用“==”和“!=”比较的,但是它们的包装类也可以吗?对于-127 ~ 128范围内的 Integer 和 Long ,我们可以直接这么比较。但是在此之外的,必须使用 equals 来比较,或者使用 Integer.intValue() 或 Long.longValue() 获取数值,再进行比较。因为对于对象来说,“==” 和 “!=” 比较的是对象的引用,不是数值的大小。可以使用 equals ,是因为基本类型的包装类已经重写了 equals 方法,用于进行对值的比较。而 -127 ~ 128 ,是包装类已经做了缓存,方便我们进行数值较小数值的比较。让我们下面看下这里面的具体源码。
/**
* Compares this object to the specified object. The result is
* {@code true} if and only if the argument is not
* {@code null} and is a {@code Long} object that
* contains the same {@code long} value as this object.
*
* @param obj the object to compare with.
* @return {@code true} if the objects are the same;
* {@code false} otherwise.
*/
public boolean equals(Object obj) {
if (obj instanceof Long) {
return value == ((Long)obj).longValue();
}
return false;
}
private static class LongCache {
private LongCache(){}
static final Long cache[] = new Long[-(-128) + 127 + 1];
static {
for(int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}
逻辑操作符,与或非,“&&”、“||”、“!”,只能应用于布尔值。在逻辑运算时,存在着短路现象。当“&&”前面false时后面的就不用运算了;当“||”前面true时,后面也不需要运算了。
直接常量。直接常量后面的后缀字符标志了它的类型,L(或小写l)表示long,F(或小写f)表示float,D(或小写d)表示double。十六进制数前缀0X(或0x),八进制数前缀0。由于小写的 l 与1看起来很像,所以建议大家使用大写的 L 。
指数计数法,1.39e-43f,实际是指1.39乘以10的负43次方;47e47是指4.7乘以10的48次方。此处的e(或大写E),是指10,而不是自然对数的基数(java用Math.E表示)。
按位操作符。按位操作符用来操作整数基本数据类型中的单个比特(bit),即二进制位。按位与(&),11为1,其余为0;按位或(|),00为0,其余为1;按位异或(^)10、01为1,11、00为0,即相同为0,不同为1;按位非(~),取反操作。其中,按位非是一元操作符,不能与=联合使用。
移位操作符。移位操作符的操作对象也是二进制的位,只可处理整数类型。左移操作符(<<),数左移,低位补0;“有符号”右移操作符(>>),数右移,正数高位插入0,负数高位插入1;“无符号”右移操作符(>>>),无论正负数,高位都插入0。
三元操作符if-else。boolean-exp ? v0 : v1;如果布尔表达式结果为true,则值为v0,否则为v1。
截尾与舍入。float或double转化为整型时,总是对该数字进行截尾,如0.7变为0;使用java.lang.Math的round()方法,可以实现舍入,即四舍五入。
第五章 控制流
程序必须在执行过程中控制程序流程并作出选择,涉及关键字if-else、while、do-while、for、return、break、switch。所有的条件语句都利用条件表达式的真或假来决定执行路径。需要注意的是,java中,不允许使用数字表示布尔值,boolean类型,只有true和false。
if-else语句是控制程序流程的最基本的形式,属于判断语句。while,先判断,条件为真时执行;do-while,先执行一次,再去判断条件,条件为真继续执行,属于迭代语句。for循环,最常用的迭代语句,在第一次迭代前要进行初始化,随后进行条件判断,且在每一次执行后进行某种形式的“步进”。for里面包含三部分,初始化语句、条件判断语句、步进运算语句,三种语句用分号分割。
Foreach语句,Java SE5引入的一种更加简洁的for语法,用于数组和容器,表示不必创建int变量去对访问项构成的序列进行计数,foreach将自动产生每一项。结构为,变量类型 变量名 : 要循环的数组或集合。
return关键字有2个用处,一个是指定一个方法返回什么值(假设它没有void返回值);另一方面它会导致当前的方法退出,并返回那个值。如果在返回void的方法中没有return语句,那么在该方法的结尾处会有一个隐式的return。
break和continue。在任何迭代语句的主体部分,都可以用break和continue控制循环的流程。break,跳出当前循环,不再循环;continue,跳出此次循环,此次循环终止(不再执行循环体内continue后的语句),进入下一次的循环。在多层循环嵌套中,它们可以结合标签使用,直接终止外层的嵌套。标签的作用,是终止后,跳到标签的位置,从而可以终止外层的循环。要记住的重点是:在Java中需要使用标签的唯一理由就是因为有循环嵌套存在,而且想从多层嵌套中break或continue。
switch有时也被划归为一种选择语句,根据整数表达式(int、char或枚举)的值,switch语句可以从一系列代码中选出一段去执行。结构为:
switch(整数选择因子){
case v1 : statement;break;
case v2 : statement;break;
……
default:statement;
}