OCA/OCP Java Note (2): Java Building Blocks (2)

4. Creating Objects

4.1. Constructors

  构造器的两个重要特征是名称与类名相同,且没有返回类型,下面的Chick() 不是构造器,因为它有返回类型void:

public void Chick() { } // NOT A CONSTRUCTOR

4.2. Reading and Writing Object Fields

 

4.3. Instance Initializer Blocks

  在大括号中的内容成为代码块(code block),在方法外面出现的代码段称为实例初始化器(instance initializers)。相关内容在Class Design一节中阐述。

4.4. Order of Initialization

  字段和实例初始化器按其在文件中出现的顺序进行初始化,构造器在所有字段和实例初始化器初始化完毕后才运行。下面看一个例子:

public class Chick {
    private String name = "Fluffy";
    {System.out.println("setting field");}
    public Chick() {
        name = "Tiny";
        System.out.println("setting constructor");
    }
    public static void main(String[] args) {
        Chick chick = new Chick();
        System.out.println(chick.name); 
    } 
}

输出是:
setting field
setting constructor
Tiny

  再看一个例子:
public class Egg {
    public Egg() {
        number = 5;
    }
    public static void main(String[] args) {
        Egg egg = new Egg();
        System.out.println(egg.number);
    }
    private int number = 3;
    {number = 4;} 
}

输出是:5 。

  注意辨别在初始化前进行访问的错误:

{ System.out.println(name); }  // DOES NOT COMPILE
private String name = "Fluffy";

5. Distinguishing Between Object References and Primitives

5.1. Primitive Types

  Java有8种内置的数据类型,如表1所示。

表1
Keyword Type Example
boolean true or false true
byte 8-bit integral value 123
short 16-bit integral value 123
int 32-bit integral value 123
long 64-bit integral value 123
float 32-bit floating-point value 123.45f
double 64-bit floating-point value 123.456
char 16-bit Unicode value ‘a’

 

需要注意,float类型字面值需要在数字末尾加上f ,如123.45f ;形如123.456 的字面值为double类型。Java默认整数字面值为int类型,最大的int型数值为2^31-1 = 2,147,483,647,如要使用long,需要在数字末尾加上L 或l :

long max = 3123456789;  // DOES NOT COMPILE
long max = 3123456789L;  // now Java knows it is a long

第1行无法编译,Java默认3123456789 为int类型,但这个数字超过了int所能容纳的范围,导致编译错误。第二行在数字末尾加上L ,告诉Java这是一个long型,可以编译。虽然可以使用大写L 或小写l ,一般使用的是大写,因为小写l 容易与数字“1”混淆。

十进制之外的表示方法:

  • 2进制:数字前加“0b”或“0B”,如0b10。
  • 8进制:数字前加“0”,如017。
  • 16进制:数字前加“0x”或“0X”,如0xFF。

Java 7中新加入了一个功能,可以在字面值中加入下划线“_”来提高可读性:

int million1 = 1000000;
int million2 = 1_000_000;

除了在字面值开头、末尾、小数点前、小数点后这几个位置,可以在字面值的任意位置加下划线“_”。
double notAtStart = _1000.00;        // DOES NOT COMPILE 
double notAtEnd = 1000.00_;          // DOES NOT COMPILE 
double notByDecimal = 1000_.00;      // DOES NOT COMPILE 
double annoyingButLegal = 1_00_0.0_0;  // this one compiles

5.2. Reference Types

  引用类型指向对象(Object),即指向类的实例。一个引用可以指向同类型的其他对象,也可以通过new关键词指向一个新对象。

5.3. Key Differences

基本类型和引用类型主要有一下三点区别:

  • 引用类型可以被赋值为null ,表示该引用当前不指向任何对象;基本类型赋值为null 会导致编译错误:

int value = null;   // DOES NOT COMPILE
String s = null;

  • 引用类型不为null 时,可以通过引用来调用方法;基本类型本身不具备任何方法可供调用:

String reference = "hello";
int len = reference.length();
int bad = len.length(); // DOES NOT COMPILE

  • 所有基本类型的名称都是小写,Java自带的所有类首字母都是大写,在编写自己的代码时,也应当遵守这个惯例。

6. Declaring and Initializing Variables

6.1. Declaring Multiple Variables

6.2. Identifiers

  合法的标识符须遵守一下规则:

  • 必须由字母、$ 或_ 开头。
  • 后续字符可以是数字。
  • 不能使用与Java保留字相同的名称。

7. Understanding Default Initialization of Variables

7.1. Local Variables

  本地变量是在方法中定义的变量,使用前必须进行初始化。本地变量没有默认值,在初始化前,里面保存的是垃圾数据。编译器会阻止你读取尚未初始化的值,如:

public int notValid() {
    int y = 10; 
    int x; 
    int reply = x + y; // DOES NOT COMPILE
    return reply;
}

  执行int reply = x + y; 时x尚未初始化,出现编译错误:
Test.java:5: variable x might not have been initialized
        int reply = x + y;
              ^

  编译器还可以识别更复杂的情况,如存在分支时,可能存在访问未初始化本地的变量的机会:
public void findAnswer(boolean check) {
    int answer;
    int onlyOneBranch;
    if (check) {
        onlyOneBranch = 1;
        answer = 1;
    } else {
        answer = 2;
    }
    System.out.println(answer);
    System.out.println(onlyOneBranch); // DOES NOT COMPILE
}

  上面的例子中,onlyOneBranch 只在一个分支进行了初始化,如果check 为false,运行至System.out.println(onlyOneBranch); 时onlyOneBranch 并没有初始化。编译器会识别出这里的问题,给出编译错误。

7.2. Instance and Class Variables

  实例和类变量不要求初始化,它们会在定义的时候获得一个初始值。不同数据类型的默认初始值如表2所示。

表2
Variable type Default initialization value
boolean false
byte, short, int, long 0 (in the type’s bit-length)
float, double 0.0 (in the type’s bit-length)
char ‘\u0000’ (NUL)
All object references (everything else) null