程序不包含适合于入口点的静态main_常见易错的Java static面试题,你不一定都能答对...

1d328d738995456ddf2f02a01432be47.png

#新人扶持计划#

今天我们来看下几个易错的static相关的Java面试题。

1、下面这段代码的输出结果是什么?

public class Test extends Base{    static{        System.out.println("test static");    }    public Test(){        System.out.println("test constructor");    }    public static void main(String[] args) {        new Test();    }}class Base{    static{        System.out.println("base static");    }    public Base(){        System.out.println("base constructor");    }}

输出结果为:

base statictest staticbase constructortest constructor

这段代码的执行过程:

① 找到main方法入口,main方法是程序入口,但在执行main方法之前,要先加载Test类

② 加载Test类的时候,发现Test类继承Base类,于是先去加载Base类

③ 加载Base类的时候,发现Base类有static块,而是先执行static块,输出base static结果

④ Base类加载完成后,再去加载Test类,发现Test类也有static块,而是执行Test类中的static块,输出test static结果

⑤ Base类和Test类加载完成后,然后执行main方法中的new Test(),调用子类构造器之前会先调用父类构造器

⑥ 调用父类构造器,输出base constructor结果

⑦ 然后再调用子类构造器,输出test constructor结果

2、这段代码的输出结果是什么?

public class Test {    Person person = new Person("Test");    static{        System.out.println("test static");    }    public Test() {        System.out.println("test constructor");    }    public static void main(String[] args) {        new MyClass();    }}class Person{    static{        System.out.println("person static");    }    public Person(String str) {        System.out.println("person "+str);    }}class MyClass extends Test {    Person person = new Person("MyClass");    static{        System.out.println("myclass static");    }    public MyClass() {        System.out.println("myclass constructor");    }}

输出结果为:

test staticmyclass staticperson staticperson Testtest constructorperson MyClassmyclass constructor

我们来分析下这段代码的执行过程:

① 找到main方法入口,main方法是程序入口,但在执行main方法之前,要先加载Test类

② 加载Test类的时候,发现Test类有static块,而是先执行static块,输出test static结果

③ 然后执行new MyClass(),执行此代码之前,先加载MyClass类,发现MyClass类继承Test类,而是要先加载Test类,Test类之前已加载

④ 加载MyClass类,发现MyClass类有static块,而是先执行static块,输出myclass static结果

⑤ 然后调用MyClass类的构造器生成对象,在生成对象前,需要先初始化父类Test的成员变量,而是执行Person person = new Person(“Test”)代码,发现Person类没有加载

⑥ 加载Person类,发现Person类有static块,而是先执行static块,输出person static结果

⑦ 接着执行Person构造器,输出person Test结果

⑧ 然后调用父类Test构造器,输出test constructor结果,这样就完成了父类Test的初始化了

⑨ 再初始化MyClass类成员变量,执行Person构造器,输出person MyClass结果

⑩ 最后调用MyClass类构造器,输出myclass constructor结果,这样就完成了MyClass类的初始化了

3、这段代码的输出结果是什么?

public class Test {    static{        System.out.println("test static 1");    }    public static void main(String[] args) {    }    static{        System.out.println("test static 2");    }}

输出结果为:

test static 1test static 2

虽然在main方法中没有任何语句,但是还是会输出。static块可以出现类中的任何地方(只要不是方法内部,记住,任何方法内部都不行),并且执行是按照static块的顺序执行的。

4、这段代码的输出结果是什么?

public class Test {public static void main(String[] args) {new MyClass();}}class SuperClass {// 父类静态构造代码块static {System.out.println("superClass static block");}// 父类构造函数public SuperClass() {System.out.println("SuperClass constructor");}// 父类构造代码块{System.out.println("superClass block");}// 父类静态变量private static SuperStaticVariable staticVariable = new SuperStaticVariable();// 父类实列变量private SuperVariable variable = new SuperVariable();}class SuperStaticVariable {public SuperStaticVariable() {System.out.println("SuperStaticVariable init");}}class SuperVariable {public SuperVariable() {System.out.println("SuperVariable init");}}class MyClass extends SuperClass {// 子类静态变量static {System.out.println("myclass static");}// 子类静态变量private static MyClassStaticVariable staticVariable = new MyClassStaticVariable();// 子类构造函数public MyClass() {System.out.println("myclass constructor");}// 子类构造代码块{System.out.println("myclass block");}// 子类实列变量private MyClassVariable variable = new MyClassVariable();}class MyClassStaticVariable {public MyClassStaticVariable() {System.out.println("MyClassStaticVariable init");}}class MyClassVariable {public MyClassVariable() {System.out.println("MyClassVariable init");}}

输出结果为:

superClass static blockSuperStaticVariable initmyclass staticMyClassStaticVariable initsuperClass blockSuperVariable initSuperClass constructormyclass blockMyClassVariable initmyclass constructor

如果类还没有被加载:

① 先执行父类的静态代码块和静态变量初始化,并且静态代码块和静态变量的执行顺序只跟代码中出现的顺序有关

② 执行子类的静态代码块和静态变量初始化

③ 执行父类的构造块和父类的实例变量初始化,并且代码块和实例变量的执行顺序只跟代码中出现的顺序有关

④ 执行父类的构造函数

⑤ 执行子类的构造块和子类的实例变量初始化

⑥ 执行子类的构造函数

如果类已经被加载:

则静态代码块和静态变量就不用重复执行,再创建类对象时,只执行与实例相关的变量初始化和构造方法。

总结

加载的顺序:父类的static成员变量 -> 子类的static成员变量 -> 父类的成员变量 -> 父类构造 -> 子类成员变量 -> 子类构造

static只会加载一次,所以通俗点讲第一次new的时候,所有的static都先会被全部载入(以后再有new都会忽略),进行默认初始化。在从上往下进行显示初始化。这里静态代码块和静态成员变量没有先后之分,谁在上,谁就先初始化

构造代码块是什么?把所有构造方法中相同的内容抽取出来,定义到构造代码块中,将来在调用构造方法的时候,会去自动调用构造代码块。构造代码快优先于构造方法。

欢迎小伙伴们关注转发点赞,谢谢~~

8882cd160573d30050205a18e760af28.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值