类成员初始化
2015-12-20 21:39
295 查看
在类内部:初始化的顺序
静态的成员变量;
普通的成员变量;
构造器的调用。
在派生类中:初始化的顺序
调用基类的构造器
按声明顺序调用成员的初始化方法
调用派生类构造器主体
大多数类的初始化都是按照这些顺序结合在一起的。
下面是一个例子:
下面我们看看输出的结果:
我们在main()方法中调用了new一个test的对象,由于test继承了sub,而sub继承了super。(当进行继承时,我们已经知道基类的一切,并且可以访问基类中任何声明为public和protected的成员。这意味着在派生类中,必须假定基类的所有成员都是有效的。一种标准方法是,构造动作一经发生,那么对象所有部分的全体成员都会得到构建。然而,在构造器内部,我们必须确保所要使用的成员都已经构建完毕。为确保这一目的,唯一的办法就是首先调用基类的构造器。那么在进入派生类构造器时,在基类中可供我们访问的成员都已得到初始化。)
只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
所以static变量是最先初始化的,并根据基类到派生类的顺序。
当static变量初始化之后,下一个执行的就是基类super的实例变量,然后在轮到super的构造器。
接着就是sub的实例变量和构造器。我们可以看到sub的构造器执行之前有sub fun1的输出。这就证明是先初始化实例变量再执行构造器的。
当基类都初始化完成时,在轮到派生类。
实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。而静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
也就是说实例变量在每个对象的创建都会初始化,而静态变量只会在第一次加载类时初始化(只会初始化一次)。
下面是一个例子:
根据上面所说的顺序,相信大家都会看得懂的。
静态的成员变量;
普通的成员变量;
构造器的调用。
在派生类中:初始化的顺序
调用基类的构造器
按声明顺序调用成员的初始化方法
调用派生类构造器主体
大多数类的初始化都是按照这些顺序结合在一起的。
下面是一个例子:
public class Test extends Sub{ public static int field = getField2(); public Test(){ System.out.println("test()"); } public static void main(String[] args) { new Test(); } public static int getField2(){ System.out.println("test static"); return 1; } } class Super{ public Super(){ System.out.println("super()"); } public int field = 0; public static int field2 = getField2(); public void fun1(){ System.out.println("super fun1"); } public int getField(){ return field; } public static void fun2(){ System.out.println("super static fun2"); } public static int getField2(){ fun2(); return 1; } } class Sub extends Super{ public Sub(){ System.out.println("sub()"); } public int field = getField(); public static int field2 = getField2(); public void fun1(){ System.out.println("sub fun1"); } public int getField(){ fun1(); return 1; } public static void fun2(){ System.out.println("sub static fun2"); } public static int getField2(){ fun2(); return 1; } }
下面我们看看输出的结果:
output: super static fun2 sub static fun2 test static super() sub fun1 sub() test() 成功构建 (总时间: 0 秒)
我们在main()方法中调用了new一个test的对象,由于test继承了sub,而sub继承了super。(当进行继承时,我们已经知道基类的一切,并且可以访问基类中任何声明为public和protected的成员。这意味着在派生类中,必须假定基类的所有成员都是有效的。一种标准方法是,构造动作一经发生,那么对象所有部分的全体成员都会得到构建。然而,在构造器内部,我们必须确保所要使用的成员都已经构建完毕。为确保这一目的,唯一的办法就是首先调用基类的构造器。那么在进入派生类构造器时,在基类中可供我们访问的成员都已得到初始化。)
只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。
所以static变量是最先初始化的,并根据基类到派生类的顺序。
当static变量初始化之后,下一个执行的就是基类super的实例变量,然后在轮到super的构造器。
接着就是sub的实例变量和构造器。我们可以看到sub的构造器执行之前有sub fun1的输出。这就证明是先初始化实例变量再执行构造器的。
当基类都初始化完成时,在轮到派生类。
实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变量才会被分配空间,才能使用这个实例变量。而静态变量不属于某个实例对象,而是属于类,所以也称为类变量,只要程序加载了类的字节码,不用创建任何实例对象,静态变量就会被分配空间,静态变量就可以被使用了。总之,实例变量必须创建对象后才可以通过这个对象来使用,静态变量则可以直接使用类名来引用。
也就是说实例变量在每个对象的创建都会初始化,而静态变量只会在第一次加载类时初始化(只会初始化一次)。
下面是一个例子:
public class ExplicitStatic { public static void main(String[] args) { System.out.println("Inside main()"); Cups.cup1.f(99); } static Cups cup1 = new Cups(); static Cups cup2 = new Cups(); } class Cup { Cup(int marker) { System.out.println("Cup("+marker+")"); } void f(int marker){ System.out.println("f(" + marker + ")"); } } class Cups { static Cup cup1; static Cup cup2; public int field = getField(); static { cup1 = new Cup(1); cup2 = new Cup(2); } Cups() { System.out.println("Cups()"); } public int getField(){ System.out.println("field"); return 1; } }
output: Cup(1) Cup(2) field Cups() field Cups() Inside main() f(99) 成功构建 (总时间: 1 秒)
根据上面所说的顺序,相信大家都会看得懂的。
相关文章推荐
- Java中异常处理和设计
- Java按位操作符
- 如何让app适应不同分辨率(转)
- 精确乘幂
- 开源的魅力:利用CMake编译Opencv源代码
- mysql用户管理
- js页面之间传参2
- gridview--基本的gridview
- boa安装
- 源码安装lua
- 详解WebApp与Native App的区别(转)
- 五、在myeclipse中查询与添加索引实例
- DZNEmptyDataSet
- Android中Parcelable接口用法
- Android 怎么录制视频
- 软件工程总结
- html知识小结
- Android中Activity启动模式详解(转)
- JavaScript 浮点数及运算精度调整总结,浮点数计算不准确怎么办
- 狼道文化