A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

胡军

中级黑马

  • 黑马币:0

  • 帖子:15

  • 精华:0

© 胡军 中级黑马   /  2013-3-29 11:18  /  1563 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 胡军 于 2013-3-31 14:01 编辑
  1. class Father
  2. {
  3.         static
  4.         {
  5.                 System.out.println("父类静态代码块");
  6.         }

  7.         {
  8.                 System.out.println("父类构造代码块");
  9.         }
  10. }

  11. class Son extends Father
  12. {
  13.         static
  14.         {
  15.                 System.out.println("子类静态代码块");
  16.         }

  17.         {
  18.                 System.out.println("子类构造代码块");
  19.         }

  20.         Son()
  21.         {
  22.                 System.out.println("子类无参数构造函数");
  23.         }
  24. }

  25. class StaticExtendsDemo
  26. {
  27.         public static void main(String[] args)
  28.         {
  29.                 Son s = new Son();
  30.         }
  31. }
复制代码
运行结果:
父类静态代码块
子类静态代码块
父类构造代码块
子类构造代码块
子类无参数构造函数

为什么结果是这样,为什么父类的静态代码块和构造代码块没有被覆盖呢?
是它们不能被继承还是其他原因导致的。

点评

 建议你可以去19届交流区发帖;如果问题未解决,请继续追问回复者,如果问题已经解决,请将分类改为“已解决”,谢谢  发表于 2013-3-30 17:34

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

5 个回复

倒序浏览
静态代码块:要明白静态代码块是给类初始化,随着类的加载而执行,并且优于主函数执行且只运行一次;所以静      态代码块只要定义了就会随着类的加载而运行。
构造代码块:是给本类所有对象初始化,并且优先于构造函数执行。
关于覆盖的问题我认为java中在子类继承父类或者子类实现接口的时候,只有父类和接口中的方法才能覆盖,即覆盖知识针对方法而言的。(自己的理解)

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 刘焕新 于 2013-3-29 12:51 编辑

当父类与子类都有静态代码块、初始化块构造函数的时候,执行顺序如下:
父类静态代码块  > 子类静态代码块  >
父类初始化块 > 子类初始化块 >
父类构造函数  > 子类构造函数
(先有父亲,后有孩子)
父类的非静态方法可以被子类重写(也就是覆盖);而静态方法和静态代码块只能被继承,重写无效,即不构成多态。
子类执行创建对象时,会先上溯寻找父类及其祖宗类,如果是多级继承,则最顶级的父类会先执行对象的创建,再依次往下创建子孙类对象;
例如上面的代码,准备执行"Son s = new Son()"时,虚拟机会先去寻找Son类的父辈类。
其实还可以这样看,所有Object的子类的构造函数内部都会隐式包含一条super()语句,如:
  1. Son()  
  2. {
  3.     super();    //而super()的意思正是上溯寻找它的父类及其调用无参构造函数。
  4.      ...
  5. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
静态代码块的初始化顺序

class Parent{
static String name = "hello";
{
System.out.println("parent block");
}
static {
System.out.println("parent static block");
}
public Parent(){
System.out.println("parent constructor");
}
}

class Child extends Parent{
static String childName = "hello";
{
System.out.println("child block");
}
static {
System.out.println("child static block");
}
public Child(){
System.out.println("child constructor");
}
}

public class StaticIniBlockOrderTest {

public static void main(String[] args) {
new Child();//语句(*)
}
}
问题:当执行完语句(*)时,打印结果是什么顺序?为什么?
解答:当执行完语句(*)时,打印结果是这样一个顺序 :
parent static block
child static block
parent block
parent constructor
child block
child constructor
分析:当执行new Child()时,它首先去看父类里面有没有静态代码块,如果有,它先去执行父类里面静态代码块里面的内容,当父类的静态代码块里面的内容执行完毕之后,接着去执行子类(自己这个类)里面的静态代码块,当子类的静态代码块执行完毕之后,它接着又去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法,这个就是一个对象的初始化顺序。

总结:
对象的初始化顺序:首先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方法,然后执行子类非静态代码块和构造方法。

注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
王杰123 发表于 2013-3-29 16:17
静态代码块的初始化顺序

class Parent{

多谢讲解,顺便问一句如何把主题改为已解决啊
回复 使用道具 举报
胡军 发表于 2013-3-30 10:21
多谢讲解,顺便问一句如何把主题改为已解决啊

你在重新编辑一下 帖子,把它设置为已解决。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马