第3章 关系操作符
3.1 测试对象的等价性
== 和 != 比较的是对象的引用
特殊方法equals() 的默认行为也是比较引用
1. n1 和 n2 是两个不同的引用(明显是两个不同的存储区域),所以二者 !=。
2. equals() 方法是所有对象的特殊方法(继承自Object类),Integer重定义了equals()方法以比较其内容是否相等,所以这里n1.equals(n2) 为 true。equals()不适用于“基本类型”,基本类型直接使用==和!=即可。
3. v1.equals(v2)为 false 验证了 equals()方法默认行为是比较引用,除非在自定义类Value中重定义 equals()方法。
3.2 直接常量
有时直接常量的类型是模棱两可的,这就需要与直接常量相关的某些字符来额外增加一些信息以“指导”编译器,使其能够准确地知道要生成什么样的类型。如果编译器能够正确地识别类型,就不必在数值后增加字符。
在C、C++或者Java中,二进制数没有直接常量表示方法。但是,在使用十六进制和进制的记数法时,以二进制形式显示结果将非常有用。通过使用Integer和Long类的静态方法toBinaryString()可以很容易地实现这一点。注意,如果将比较小的类型传递给Integer.toBinaryString()方法,则该类型将自动转换为int。
// Literals.java
public class Literals{
public static void main(String[] args){
int i1 = 0x2f; // Hexadecimal (lowercase)
System.out.println("i1: " + Integer.toBinaryString(i1));
int i2 = 0X2F; // Hexadecimal (uppercase)
System.out.println("i2: " + Integer.toBinaryString(i2));
int i3 = 0177; // Octal (leading zero)
System.out.println("i3: " + Integer.toBinaryString(i3));
char c = 0xffff; // max char hex value
System.out.println("c: " + Integer.toBinaryString(c));
byte b = 0x7f; // max short hex value
System.out.println("b: " + Integer.toBinaryString(b));
short s = 0x7fff; // max short hex value
System.out.println("s: " + Integer.toBinaryString(s));
long n1 = 200L; // long suffix
long n2 = 200l; // long suffix (but can be confusing)
long n3 = 200;
float f1 = 1;
float f2 = 1F; // float suffix
float f3 = 1f; // float suffix
double d1 = 1d; // double suffix
double d2 = 1D; // dobule suffix
// (Hex and Octal also work with long)
}
指数计数法。在C、C++以及Java中,e 代表“10的幂次”,与科学与工程领域中“e”代表自然对数的基数(约等于2.718,Java中的Math.E给出了更精确的double型的值)不同。
根据John Kirkham的描述,Java语言中 e 与 科学工程领域不同,可能跟60年代的FORTRAN有关。
// Exponents.java
// "e" means "10 to the power."
public class Exponents {
public static void main(String[] args){
// Uppercase and lowercase 'e' are the same:
float expFloat = 1.39E-43f;
expFloat = 1.39e-43f;
System.out.println(expFloat);
double expDouble = 47e47d; // 'd' is optional
double expDouble2 = 47e47; // Automaticall double
System.out.println(expDouble);
}
3.3 类型转换(cast)操作符
Java中布尔类型,不允许进行任何类型的转换处理,其它基本类型都可转换成别的基本数据类型。
将float和double转型为整型值时,总是对该数字执行截尾。如果想要得到舍入的结果,就需要使用java.lang.Math中的round()方法。
// CastingNumbers.java
// What happens when you cast a float or double to an integral value ?
public class CastingNumbers{
public static void main(String[] args){
double above = 0.7, below = 0.4;
float fabove = 0.7f, fbelow = 0.4f;
System.out.println("(int)above: " + (int)above);
System.out.println("(int)below: " + (int)below);
System.out.println("(int)fabove: " + (int)fabove);
System.out.println("(int)fbelow: " + (int)fbelow);
System.out.println("Math.round(above): " + Math.round(above));
System.out.println("Math.round(above): " + Math.round(above));
System.out.println("Math.round(below): " + Math.round(below));
System.out.println("Math.round(fabove): " + Math.round(fabove));
System.out.println("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
*/
提升。如果对基本类型执行算术运算或按位运算,只要类型比int小(即char、byte或者short),那么在运算之前,这些值会自动转换成int。这样一来,最终生成的结果就是int型。如果想把结果赋值给较小的类型,就必须使用类型转换(既然把结果赋给了较小的类型,就可能出现信息丢失)。通常,表达式中出现的最大的数据类型决定了表达式最终结果的数据类型。如果一个float值与一个double值相乘,结果就是double,如果将一个int和一个long值相加,则结果就为long。
溢出。如果对两个足够大的int值执行乘法运算,结果就会溢出。编译器不会发出错误或警告信息,运行时也不会出现异常。这说明Java虽然是好东西,但也没有那么好!
// Overflow.java
// Surprise! Java lets you overflow.
public class Overflow{
public static void main(String[] args){
int big = Integer.MAX_VALUE;
System.out.println("big = " + big);
int big1 = big + 1;
System.out.println("big1 = " + big1);
int bigger = big * 4;
System.out.println("bigger = " + bigger);
}
}
/* Output:
big = 2147483647
big1 = -2147483648
bigger = -4
*/
3.4 Java没有sizeof()操作符
在C和C++中,sizeof()操作符可以告诉你为数据项分配的字节数。使用这个操作符的最大原因是为了进行一些与存储空间有关的运算,使程序可以在不同平台上“移植”。而Java不需要sizeof()操作符来满足这方面的需要,因为所有数据类型在所有机器中的大小是相同的。我们不必考虑移植问题——它已经被设计在语言中了。
第4章 控制执行流程
4.1 true 和 false
注意Java不允许我们将一个数字作为布尔值使用,这与C和C++ 不同(C/C++中,“真”是非零,而“假”是零)。如果将数字作为布尔表达式,Java编译器会直接报错。
4.2 switch
switch要求使用一个选择因子:
在JDK5之前,选择因子必须是int或char那样的整数值。
JDK1.5开始,Java增加了新特性enum,使得enum可以与switch协调工作。
JDK1.7开始,switch开始支持String作为选择因子。在switch语句中,String的比较用的是String.equals()。因此,需要注意,传给switch的String变量不能为null,同时switch的case子句中使用的字符串也不能为null。显然是因为:
如果switch传入的是null,则在运行时对null对象调用hashCode(String.equals()会调用)方法会出现NullPointException。
如果case写的是null,那么在编译时无法求出hashCode,因此编译时就会报错。
switch支持String只是一个语法糖,由javac来负责生成相应的代码。底层的JVM在switch上并没有进行修改。