阿里面试题(代码块知识点)

阿里面试题:

class HelloA {
    //构造方法
    public HelloA(){
        System.out.println("1.Hello A!父类构造方法");
    }
    //非静态代码块
    {
        System.out.println("2.i'm A class.父类非静态代码块");
    }
    //静态代码块
    static{
        System.out.println("3.static A 父类静态代码块");
    }
}
public class HelloB extends HelloA {
    //构造方法
    public HelloB(){
        System.out.println("4.Hello B! 构造方法");
    }
    //非静态代码块
    {
        System.out.println("5.i'm B class.非静态代码块");
    }
    //静态代码块
    static{
        System.out.println("6.static B 静态代码块");
    }
    public static void main(String[] args) {
        System.out.println("7.---start---");
        new HelloB();
        new HelloB();
        System.out.println("8.---end---");
    }
}

问:请写出上述代码的输出。
解析:
先从main方法入口,
类加载时,要用到HelloB这个类就加载它的静态类,然后又发现HelloB这个类继承自HelloA,所以先加载HelloA的静态块,在加载HelloB的静态块,
继续往下走,输出“—start—”这条语句,
再然后看见new关键字,new了HelloB的对象,
HelloB中有构造块和构造方法,但是HelloB继承自HelloA,
HelloA中也有构造快和构造方法,所以先输出HelloA中的构造块,再输出HelloA的构造方法,再输出HelloB的构造块,再输出HelloB的构造方法,
因为new了两次,所以继续再按顺序输出一次A和B中的构造块和构造方法。
最后输出“—end—”语句。

运行结果如下:

3.static A 父类静态代码块
6.static B 静态代码块
7.---start---
2.i'm A class.父类非静态代码块
1.Hello A!父类构造方法
5.i'm B class.非静态代码块
4.Hello B! 构造方法
2.i'm A class.父类非静态代码块
1.Hello A!父类构造方法
5.i'm B class.非静态代码块
4.Hello B! 构造方法
8.---end---

分析是按自己思路来的,可能有些绕,不过我们熟悉概念后,再结合代码去看,就会很容易的理解代码块的用法及概念。

代码块

代码块定义:使用 { } 定义的一段代码。

根据代码块定义的位置以及关键字,又可分为以下四种:

  1. 普通代码块
  2. 构造快
  3. 静态块
  4. 同步代码块

1.普通代码块

出现在方法中的代码块,解决变量重命名的问题。代码块一定要写在方法变量命名前。
范例:观察普通代码块

public class Test{
    public static void main(String[] args) {
    { //直接使用{}定义,普通方法块
        int x = 10 ;
        System.out.println("x = " +x);
    }
    int x = 100 ;
    System.out.println("x = " +x);
    }
}

2.构造块

定义在类中代码块,不加任何修饰符。
优先于类中的构造方法执行,并且有多少对象产生,就调用多少次构造块。
范例:

class Person{
    {   //定义在类中,不加任何修饰符,构造块
        System.out.println("1.Person类的构造块");
    }
    public Person(){
        System.out.println("2.Person类的构造方法");
    }
}
public class Test{
    public static void main(String[] args) {
        new Person();
        new Person();
    }
}

运行结果:

1.Person类的构造块
2.Person类的构造方法
1.Person类的构造块
2.Person类的构造方法

通过上述代码我们可以发现:构造块优先于构造方法执行,每产生一个新的对象就调用一次构造块,构造块可以进行简单的逻辑操作(在调用构造方法前)

3.静态代码块

定义在类中的代码块,并且使用static修饰的代码块。
根据静态块所在的类的不同又可分为以下两种类型

  1. 在非主类中
  2. 在主类中

3.1在非主类中的静态块(和对象无关)
优先于构造块执行,无论有多少对象产生,静态块只执行一次(在类加载时执行:加载到JVM中,要用到这个类,就加载)。

范例:观察非主类中的静态块

class Person{
    {    //定义在类中,不加任何修饰符,构造块
         System.out.println("1.Person类的构造块");
    }
    public Person(){
        System.out.println("2.Person类的构造方法");
    }
    static {  //定义在非主类中的静态块
        System.out.println("3.Person类的静态块");
    }
}
public class Test{
    public static void main(String[] args) {
        System.out.println("--start--");
        new Person();
        new Person();
        System.out.println("--end--");
    }
}

运行结果:

--start--
3.Person类的静态块
1.Person类的构造块
2.Person类的构造方法
1.Person类的构造块
2.Person类的构造方法
--end--

通过以上代码我们可以发现:

  1. 静态块优先于构造块执行。
  2. 无论产生多少实例化对象,静态块都只执行一次。

静态块的主要作用是为static属性进行初始化

3.2在主类中的静态块

在主类中的静态块优先于主方法执行。
范例:定义在主类中的代码块

public class Test{
    {
        System.out.println("1.Test的构造块");
        }
    public Test(){
        System.out.println("2.Test的构造方法");
    }
    static{
        System.out.println("3.Test的静态块");
    }
    public static void main(String[] args) {
        System.out.println("--start--");
        new Test();
        new Test();
        System.out.println("--end--");
    }
}

运行结果:

3.Test的静态块
--start--
1.Test的构造块
2.Test的构造方法
1.Test的构造块
2.Test的构造方法
--end--

通过上述代码我们可以发现:在主类中定义的静态块,优先于主方法(main)执行。

猜你喜欢

转载自blog.csdn.net/qq_42711862/article/details/88976810