回忆一遥远 发表于 2017-8-20 19:53:48

0基础学习Java ——第五段 ---初始化与清理(中下)

本帖最后由 回忆一遥远 于 2017-8-20 20:54 编辑

初始化与清理


成员初始化
在 Java 中,所有变量在使用前都要能得到恰当的初始化。
对于方法的局部变量,Java 以编译错误来保证变量能够得到初始化。

例如写成下面这样就会得到一条出错信息。
static void fun() {
        int i;
        i++;
}
出错信息:

提示 i 未初始化

编译器也可以为 I 赋一个默认值,未初始化的局部变量很可能是程序员的疏忽,所以采用默认值反而会掩盖这种失误。
强制程序员提供一个初始值,能够帮忙找出程序里的缺陷。

类的每个基本类型数据成员都会有一个初始值。
下面这个例子可以看到类的初始化情况:

public class InitialValies {

        boolean t;
        char c;
        byte b;
        short s;
        int i;
        long l;
        float f;
        double d;
        InitialValies reference;
        void printInitialValies() {
                System.out.println("Data type                Initial value");
                System.out.println("boolean                        " + t);
                System.out.println("char                        [" + c + "]");
                System.out.println("byte                        " + b);
                System.out.println("short                        " + s);
                System.out.println("int                                " + i);
                System.out.println("long                        " + l);
                System.out.println("float                        " + f);
                System.out.println("double                        " + d);
                System.out.println("reference                " + reference);
        }
       
        public static void main(String[] args) {
                new InitialValies().printInitialValies();
        }
}

输出:
Data type                Initial value
boolean                        false
char                        [ ]
byte                        0
short                        0
int                                0
long                        0
float                        0.0
double                        0.0
reference                null


在类里定义一个对象引用时,如果不将其初始化,这个引用就会获得一个特殊值 null 。


指定初始化
如果想为变量赋初值,可以在定义类成员变量的地方为其赋值。
下面是修改后的代码:

public class InitialValies2 {

        boolean t = true;
        char c = 'p';
        byte b = 49;
        short s = 0xfe;
        int i = 153;
        long l = 978;
        float f = 4.64f;
        double d = 2.34569;
        InitialValies reference;
        void printInitialValies() {
                System.out.println("Data type                Initial value");
                System.out.println("boolean                        " + t);
                System.out.println("char                        [" + c + "]");
                System.out.println("byte                        " + b);
                System.out.println("short                        " + s);
                System.out.println("int                                " + i);
                System.out.println("long                        " + l);
                System.out.println("float                        " + f);
                System.out.println("double                        " + d);
                System.out.println("reference                " + reference);
        }
       
        public static void main(String[] args) {
                new InitialValies2().printInitialValies();
        }
}

输出:
Data type                Initial value
boolean                        true
char                       
byte                        49
short                        254
int                                153
long                        978
float                        4.64
double                        2.34569
reference                null


也可以初始化非基本类型对象。



构造器初始化
在运行时,可以调用方法或执行某些动作来确定初值,这给编程带来了更大的灵活性
无法阻止自动初始化的进行,自动初始化在构造器被调用之前发生。
像下面这段代码:
public class Test{
        int i;
        Test(){i = 4;}
}
首先 i 会被置零,然后变成4。

对于所有基本类型和对象引用,包括在定义时已经指定初值的变量,都会进行自动初始化。
因此编译器不会强制你一定要在构造器的某个地方或在使用它们之前对元素进行初始化。


初始化顺序
在类的内部,变量定义的先后顺序决定了初始化的顺序。
即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

下面这个例子可以说明初始化顺序:
class Window{
        Window(int marker){System.out.println("Window(" + marker + ")");}
}

class House{
        Window w1 = new Window(1);
        House(){
                System.out.println("House()");
                w3 = new Window(33);
        }
        Window w2 = new Window(2);
        void f() {System.out.println("f()");}
        Window w3 = new Window(3);
}

public class OrderOfInitialization {

        public static void main(String[] args) {
                House h = new House();
                h.f();
        }

}

输出:
Window(1)
Window(2)
Window(3)
House()
Window(33)
f()


静态数据的初始化
无论创建多少个对象,里面的静态数据都只占用一份存储区域。
static 关键字不能应用于局部变量,它只能作用于域。
在一个静态的基本类型域中,如果没对它初始化,它会获得基本类型的标准初值;如果它是一个对象引用,那么它的默认初始化值就是 null。

从一个例子来看静态区块的初始化过程:
class Bowl{
        Bowl(int marker){
                System.out.println("Bowl("+ marker +")");
        }
        void f1(int marker) {
                System.out.println("f1(" + marker + ")");
        }
}

class Table{
        static Bowl bowl1 = new Bowl(1);
        Table(){
                System.out.println("Table()");
                bowl2.f1(1);
        }
        void f2(int marker) {
                System.out.println("f2(" + marker + ")");
        }
        static Bowl bowl2 = new Bowl(2);
}

class Cupboard{
        Bowl bowl3 = new Bowl(3);
        static Bowl bowl4 = new Bowl(4);
        Cupboard(){
                System.out.println("Cupboard()");
                bowl4.f1(2);
        }
        void f3(int marker) {
                System.out.println("f3(" + marker + ")");
        }
        static Bowl bowl5 = new Bowl(5);
}

public class StaticInitialization {

        public static void main(String[] args) {
                System.out.println("Creating new Cupboard() in main");
                new Cupboard();
                System.out.println("Creating new Cupboard() in main");
                new Cupboard();
                table.f2(1);
                cupboard.f3(1);
        }
        static Table table = new Table();
        static Cupboard cupboard = new Cupboard();
}

输出:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)

从上面可以看出,初始化的顺序是先静态对象,然后是“非静态”对象。
静态对象只能被初始化一次,且在必要时刻才会进行。


显式的静态初始化
Java 允许将多个静态初始化动作组织成一个特殊的“静态子句”(“静态块”)。
例如:
public class Test{
        static int I;
        static {
                I = 67;
        }
}
这是一段跟在 static 关键字后面的代码。
当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即使没有实例化对象),它会静态初始化且只执行一次。





页: [1]
查看完整版本: 0基础学习Java ——第五段 ---初始化与清理(中下)