ThinkInJava4读书笔记之第三章控制程序流程

Java运算符

     几乎所有运算符都只能操作“主类型”(Primitives)。唯一的例外是“=”、“==”和“!=”,它们能操作所有对象(也是对象易令人混淆的一个地方)。除此以外,String 类支持“+”和“+=”。

赋值

     对主数据类型的赋值是非常直接的。由于主类型容纳了实际的值,而且并非指向一个对象的句柄,所以在为其赋值的时候,可将来自一个地方的内容复制到另一个地方。例如,假设为主类型使用“A=B”,那么B 处的内容就复制到A。若接着又修改了A,那么B 根本不会受这种修改的影响。作为一名程序员,这应成为自己的常识。

    但在为对象“赋值”的时候,情况却发生了变化。对一个对象进行操作时,我们真正操作的是它的句柄。所以倘若“从一个对象到另一个对象”赋值,实际就是将句柄从一个地方复制到另一个地方。这意味着假若为对象使用“C=D”,那么C 和D 最终都会指向最初只有D 才指向的那个对象。

class Number {
int i;
}

public class Assignment {
  public static void main(String[] args) {
     Number n1 = new Number();
     Number n2 = new Number();
     n1.i = 9;
     n2.i = 47;
     System.out.println("1: n1.i: " + n1.i + ", n2.i: " + n2.i);
     n1 = n2;
     System.out.println("2: n1.i: " + n1.i + ", n2.i: " + n2.i);
     n1.i = 27;
     System.out.println("3: n1.i: " + n1.i + ", n2.i: " + n2.i);
  }
} // 

  运行结果:

1: n1.i: 9, n2.i: 47
2: n1.i: 47, n2.i: 47
3: n1.i: 27, n2.i: 27
    改变n1 的同时也改变了n2。这是由于无论n1 还是n2 都包含了相同的句柄,它指向相同的对象(最初的句柄位于n1 内部,指向容纳了值9 的一个对象。在赋值过程中,那个句柄实际已经丢失;它的对象会由“垃圾收集器”自动清除)。

 检查对象是否相等

     关系运算符==和!=也适用于所有对象,但它们的含义通常会使初涉Java 领域的人找不到北。下面是一个例子:

class Value {
  int i;
}

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.println(n1 != n2);
        System.out.println(n1.equals(n2));
        Value v1 = new Value();
        Value v2 = new Value();
       v1.i = v2.i = 100;
       System.out.println(v1.equals(v2));
    }
}

  运行结果:

false
true
true
false

     其中,表达式System.out.println(n1 == n2)可打印出内部的布尔比较结果。一般人都会认为输出结果肯定先是true,再是false,因为两个Integer 对象都是相同的。但尽管对象的内容同,句柄却是不同的,而==和!=比较的正好就是对象句柄。所以输出结果实际上先是false,再是true。若想对比两个对象的实际内容是否相同,必须使用所有对象都适用的特殊方法equals()。但这个方法不适用于“主类型”,那些类型直接使用==和!=即可。是由于equals()的默认行为是比较句柄。所以除非在自己的新类中改变了equals(),否则不可能表现出我们希望的行为。大多数Java 类库都实现了equals(),所以它实际比较的是对象的内容,而非它们的句柄。

 造型运算符

void casts() {

  int i = 200;

  long l = (long)i;

  long l2 = (long)200;

}

  在Java 里,造型则是一种比较安全的操作。但是,若进行一种名为“缩小转换”(Narrowing Conversion)的操作(也就是说,脚本是能容纳更多信息的数据类型,将其转换成容量较小的类型),此时就可能面临信息丢失的危险。此时,编译器会强迫我们进行造型,而对于“放大转换”(Widening conversion),则不必进行明确造型,因为新类型肯定能容纳原来类型的信息,不会造成任何信息的丢失。

    Java 允许我们将任何主类型“造型”为其他任何一种主类型,但布尔值(bollean)要除外,后者根本不允许进行任何造型处理。“类”不允许进行造型。为了将一种类转换成另一种,必须采用特殊的方法(字串是一种特殊的情况,子类和父类之间可以进行转换)。

    在char,byte 和short 中,算术运算符具有“转型”效果。对这些类型的任何一个进行算术运算,都会获得一个int 结果。必须将其明确“造型”回原来的类型(缩小转换会造成信息的丢失),以便将值赋回那个类型。但对于int 值,却不必进行造型处理,因为所有数据都已经属于int 类型。然而,不要放松警惕,认为一切事情都是安全的。如果对两个足够大的int 值执行乘法运算,结果值就会溢出。

 执行控制

Java 使用了C 的全部控制语句,在Java 里,涉及的关键字包括if-else、while、do-while、for 以及一个名为switch 的选择语句。然而,Java 并不支持非常有害的goto,将其作为保留关键字

Switch开关

switch(整数选择因子) {

case 整数值1 : 语句; break;

case 整数值2 : 语句; break;

//..

default:语句;

}

switch要求使用一个选择因子,并且必须是int 或char 那样的整数值。例如,假若将一个字串或者浮点数作为选择因子使用,那么它们在switch 语句里是不会工作的。

你可能感兴趣的:(java)