黑马程序员技术交流社区
标题:
静态代码块、构造代码块和构造函数的特点及加载顺序
[打印本页]
作者:
李云飞
时间:
2013-1-18 09:48
标题:
静态代码块、构造代码块和构造函数的特点及加载顺序
本帖最后由 张向辉 于 2013-1-19 12:35 编辑
class Person
{
Person()
{
System.out.println("-----------构造函数------------");
}
{
System.out.println("-----------构造代码块------------");
}
static
{
System.out.println("-----------静态代码块------------");
}
}
class Test2
{
public static void main(String[] args)
{
Person p1 = new Person();
Person p2 = new Person();
}
}
运行结果:
-------------------静态代码快-------------------
-------------------构造代码快-------------------
-------------------构造函数----------------------
-------------------构造代码快-------------------
-------------------构造函数----------------------
以下是我的理解:
1.静态代码块和构造代码的作用范围是整个类,用于初始化一个类中的共性属性,构造函数的作用范围是某一个特定的类,用于初始化一个类中的特有属性;
2.静态代码块是随着类的加载而加载,构造代码块和构造函数是随着对象的创建而加载,因此它们的加载顺序是:静态代码块、构造代码块、构造函数;
3.静态代码块随着类的加载而加载但仅加载一次,而构造代码块与构造函数是随着对象的加载而加载,每当new一个对象时就会加载一次。
可以如上理解静态代码块与构造代块的特点及加载顺序吗?或者还有其他的一些特点,请高手指点。谢谢!
作者:
唐晓
时间:
2013-1-18 10:21
静态代码块是在new对象后自动加载,而且只加载一次。运行完静态代码块后然后才运行new之后的构造函数。
构造代码块是new加载完后首先执行,早于构造函数。
所以 Person p1 = new Person();后运行顺序是静态代码块->构造代码块->构造函数.
Person p2 = new Person();由于静态代码块已经被加载,只能运行一次,所以运行后顺序是构造代码块->构造函数.
作者:
高浩
时间:
2013-1-18 14:14
关于静态的东西,都是随着类文件的加载而加载出来,所以它应该首当其冲的。
作者:
折纸时代
时间:
2013-1-18 19:27
其实这类的问题,最好的方法就是自己写一下.
把可以有执行语句的地方写上打印语句,打印字符串用以标记分类.
class Root
{
static{
System.out.println("Root的静态初始化块");
}
{
System.out.println("Root的普通初始化块");
}
public Root()
{
System.out.println("Root的无参数的构造器");
}
}
class Mid extends Root
{
static{
System.out.println("Mid的静态初始化块");
}
{
System.out.println("Mid的普通初始化块");
}
public Mid()
{
System.out.println("Mid的无参数的构造器");
}
public Mid(String msg)
{
//通过this调用同一类中重载的构造器
this();
System.out.println("Mid的带参数构造器,其参数值:"
+ msg);
}
}
class Leaf extends Mid
{
static{
System.out.println("Leaf的静态初始化块");
}
{
System.out.println("Leaf的普通初始化块");
}
public Leaf()
{
//通过super调用父类中有一个字符串参数的构造器
super("疯狂Java讲义");
System.out.println("执行Leaf的构造器");
}
}
public class Test
{
public static void main(String[] args)
{
new Leaf();
new Leaf();
}
}
复制代码
问题点:
1. 静态初始化块
2.非静态初始化块
3. 构造器
所谓静态:
就是在类加载时,就随着类也加载了. 或者说,静态的成员都是类成员,随着类的加载而加载.
不像非静态成员变量,必须要创建对象.
那它们的运行顺序呢?
其实,上面的代码可以很清楚的看到结果.
1. 首先,通过new来创建对象,在此之前呢.会先初始化该类,又因为,java在加载某类时,会把该类的所以父类(至Object)都进行初始化操作.
2. 因为,static修饰的成员都是类成员,会随着类的加载而执行. 所以,会从最高父类执行静态初始化块,然后是其子类.就是把静态初始化块从上到下执行个遍.
3. 然后对象被创建了, 因为java的运行机制,所以还得再重复刚才的动作,不过这次是非静态初始化块和构造器.
4.非静态初始化块优先于该类构造器,但又因是父类,所以两者都优先于其子类执行. 过程就是,最高父类的非静态代码块 --> 构造器--> 其子类非静态代码块 --> 构造器
最后 执行到最底层的子类.
5. 又通过new创建了个对象,因为静态的成员已经存在,所以无须再次创建.只是再次执行非静态便可.把从第3步到 第4步重复一遍..
至此,整个程序运行结束!
作者:
黑马-小龙
时间:
2013-1-18 20:57
现在,这个代码一共用了3片, 内存空间!
分别是 : 堆 、栈 、 方法区! 对不对, 而方法区, 又分为, 普通方法区 和静态方法区!
而加载的顺序是先加载, 方法区,在加载堆, 随着对象对函数的引用才使用到栈。
主函数,在实例化对象的时候, 先加载类中的静态成员变量,方法 静态方法, 静态代码块 放到方法区中。
而静态代码块,是随着类的加载而加载,而且是放到方法区的所以,只加载了一次。 (方法区的类只能加载一次)
而构造代码块和构造函数 是随着对象的的加载而加载。 先加载,构造代码块,最后才 调用构造函数。返回到,主函数中的 Person 变量里。
为什么先加载了构造代码块而后加载了 构造函数,构造代码块是加载对象的时候,起一个初始化的作用
如果,先加载构造函数,这个对象就返回了呀!{:soso_e127:}
而你又有new 了一次,所以,堆内存中,又开辟了一块空间,来加载新的对象,而构造代码块和构造函数 是随着对象的的加载。所以,构造代码块
和 构造函数又加载了一次!
所你 你写的代码加载顺序就是, 静态代码块 构造代码块 构造函数 构造代码块 构造函数
作者:
王勇文
时间:
2013-1-18 22:11
当父类与子类都有静态代码块和构造函数的时候,执行顺序如下:
父类静态代码块 > 子类静态代码块 java虚拟机加载类时,就会执行该块代码。
父类构造函数 > 子类构造函数 (先有父亲,后有孩子)
如果是多级继承关系的话,高层的父类首先执行,然后依次递减
总结:静态优先执行,父类优先于子类执行
静态代码块是在JVM加载类的时候执行的,而且静态代码块执行且仅执行一次
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2