Java初始化

来源:互联网 发布:sql 比较运算符 编辑:程序博客网 时间:2024/06/08 15:46

1.      自动初始化

    变量使用之前进行初始化是良好的编程习惯。和C/C++相比,Java提供了完善的初始化机制,对于类的成员变量如果没有手动进行初始化,Java会进行默认初始化,C++不会做这种事情:

public class InitializeDefault {byte a;short b;int c;long d;float e;double f;char g;boolean h;public static void main(String[] args) {InitializeDefault t = new InitializeDefault();System.out.println("byte = " + t.a + "\n"+ "short = " + t.b + "\n"+ "int = " + t.c + "\n"+ "long = " + t.d + "\n"+ "float = " + t.e + "\n"+ "double = " + t.f + "\n"+ "char = " + (int)t.g + "\n"+ "boolean = " + t.h + "\n");}}

    以上代码的输出为:

byte = 0short = 0int = 0long = 0float = 0.0double = 0.0char = 0boolean = false

    所有变量都被设置成默认值了。对于函数内部的局部变量,和C/C++相同,Java不会自动对它们进行初始化,但是Java会提示编译时错误。

    对于自动进行的初始化操作,总是在用户主动初始化(如构造函数)之前发生,这是显然的。

2.      手动初始化

    成员变量手动初始化有3种方式:定义变量时直接初始化、初始化块、构造函数。直接初始化、初始化块在构造函数调用之前执行。

public class InitializeManual {InitializeManual(int a, short b) {this.a = a;this.b = b;System.out.println("constructor called");}// 定义时直接初始化int a = f1();short b = 99;int f1() {System.out.println("func f1 called");return 99;}// 初始化块{System.out.println("initialization block called");a = 50;}public static void main(String[] args) {InitializeManual t = new InitializeManual(1, (short) 2);System.out.println(t.a + " " + t.b);}}

    输出结果为:

func f1 calledinitialization block calledconstructor called1 2

    变量a调用函数f1()进行初始化,从结果可见定义变量时直接赋值、初始化块先于构造函数执行。直接赋值、初始化块的进行顺序取决于在类内的位置,从上向下依次执行,上例中成员变量a直接赋值操作在初始化块之前,所以先调用f()函数。

3.      静态变量

    静态变量对于一个类只有一个实例,与C/C++中的全局变量很像。静态变量的初始化先于非静态变量进行。虚拟机加载一个类时,静态变量就开始初始化了。什么时候一个类要被加载呢?有多种情况:(1)定义了一个类的对象;(2)访问类的静态数据或函数。还有其他几种使用到类的情况都会触发加载操作。加载只进行一次,静态变量也只初始化一次。

public class InitializeStatic {static int a;int b;// 构造函数InitializeStatic() {System.out.println("construct called");a = 10;b = 20;}// 初始化块{System.out.println("non static init block");b = 2;}// 静态初始化块static {System.out.println("static init block");a = 1;c = 2;}// 直接赋值static int c = f();static int f() {System.out.println("static func f called");return 99;}public static void main(String[] args) {InitializeStatic t = new InitializeStatic();System.out.println("a = " + t.a + " b = " + t.b + " c = " + t.c);}}

    以上代码的输出为:

static init blockstatic func f callednon static init blockconstruct calleda = 10 b = 20 c = 99

    代码中new了一个InitializeStatic对象,先进行静态成员的初始化,然后进行非静态成员的初始化,最后进行构造函数。静态变量可以在定义时初始化或在静态初始化块中初始化,这两种代码的初始化顺序取决于在类内部的声明顺序,由上而下执行,和非静态变量的初始化顺序类似。

     如果在main函数中只访问InitializeStatic的静态成员变量,不创建对象,即把InitializeStatic的main函数改成如下形式:

public static void main(String[] args) {System.out.println("InitializeStatic.a = " + InitializeStatic.a);}
    则InitializeStatic的输出为:
static init blockstatic func f calledInitializeStatic.a = 1

    这时只进行了静态成员变量的初始化操作,非静态变量还没有初始化。

4.      继承初始化

    继承时的初始化比较复杂。所有静态变量的初始化先于非静态变量的初始化,即先进行基类和派生类的静态初始化,然后进行基类初始化,最后进行派生类初始化。基类和派生类静态变量都有直接初始化和初始化块两种方式,初始化顺序按声明顺序,见上文第3点。基类初始化和派生类初始化见第1、2点。
class Base {{System.out.println("base init block");}static {System.out.println("base static init block");}Base() {System.out.println("base constructor");}}class Derive extends Base {{System.out.println("derive init block");}static {System.out.println("derive static init block");}Derive() {System.out.println("derive constructor");}}public class InitializeInherit {public static void main(String[] args) {Derive d = new Derive();}}
    以上代码输出为:

base static init blockderive static init blockbase init blockbase constructorderive init blockderive constructor









0 0
原创粉丝点击