《java面试宝典》三 类初始化和类实例化顺序

前言:

社长,4年api搬运工程师,之前做的都是一些框架的搬运工作,做的时间越长,越发感觉自己技术越菜,有同感的社友,可以在下方留言。现侧重于java底层学习和算法结构学习,希望自己能改变这种现状。
为什么大厂面试,更侧重于java原理底层的提问,因为通过底层的提问,他能看出一个人的学习能力,看看这个人的可培养潜力。随着springboot的流行,大部分的开发,起步就是springboot。也不看看springboot为什么简单?他底层是如果实现的。为什么同样出来4年,工资差别都很大?这些问题都值得我们深思(对社长自己说的)。
api工程师,顶天了,最多达到某些公司中级工资上限,很难突破高级这道坎。希望我们大家成就更好的自己。回想起往事,不会后悔。

面试的时候,经常会遇到这样的笔试题:给你两个类的代码,它们之间是继承的,每个类中有一些静态方法,静态代码块,非静态代码块,静态变量。

面试官为什么要这样考?

实际上就是考察我们对类初始化基础知识的掌握情况。

对象初始化顺序:

1.首先,初始化父类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
2.然后,初始化子类中的静态成员变量和静态代码块,按照在程序中出现的顺序初始化;
3.其次,初始化父类的普通成员变量和代码块,再执行父类的构造方法;
4.最后,初始化子类的普通成员变量和代码块,再执行子类的构造方法;

类初始化过程:

1.一个类初始化,实际上就是初始化<clinit>方法。
注意:<clinit>方法,可能不存在,需要有静态方法或者静态代码块。
2.一个子类要想初始化,需要先初始化他的父类。

类实例化过程:

类实例化就是初始化<init>方法

  1. 有几个构造方法,就有<init>方法
  2. 非静态方法和非静态代码块根据代码从上到下的顺序,依次执行。
  3. 构造器最后才调用

<clinit>方法,什么鬼?社长你在给我开玩笑吗?

在我们编写的代码中,不会存在这个方法,但是我们可以通过查看我们java文件对应的class可以发现是能找到这个方法的。

 

为了证明论证只有静态代码块或者静态方法才有<clinit>方法

public class Test1 {
    private int a=1;
    public static void main(String[] args) {

    }
}

扫描二维码关注公众号,回复: 8654585 查看本文章

 


作为一个Java开发者,对技术的追求而不仅仅停留在会用API,如果只是会用,那一辈子就是一个api程序猿,也就是大家所谓的搬砖的,我们应该深入底层,我们大家都知道我们编写的java文件,会编译成class文件,而又有多少人,去看过class文件长什么样子的。实际上class文件就是字节码文件,这涉及汇编的一些知识。后续,社长会整理出如何解析class字节码的相关文章。这里只是了解即可,知道有这么一回事。

 

难度系数:1 星

package com.fyqd.test.classload;

/**
 * Description:动物园
 * Author: 程序猿学社
 * Date:  2020/1/14 9:35
 * Modified By:
 */
public class Zoo {
    public static String staticPk = staticPk();
    public String pk = pk();

    static {
        System.out.println("父类静态代码块!");
    }

    {
        System.out.println("父类非静态代码块");
    }

    public static String staticPk() {
        System.out.println("父类静态方法!");
        return "PK";
    };

    public  String pk() {
        System.out.println("父类普通方法!");
        return "PK";
    };

    public Zoo() {
       System.out.println("父类构造器");
    }
}

测试类

public class Main {
    public static void main(String[] args) {
        Zoo zoo= new Zoo();
    }
}

各位社友觉得输出到控制台的结果应该是多少?

 


结论;我们可以发现运行的顺序排序 静态>非静态>结构。如果是属于同一个等级,例如静态方法和静态代码块,则根据代码的从上到下的顺序来执行。

难度系数:2 星

package com.fyqd.test.classload;

/**
 * Description:动物园
 * Author: 程序猿学社
 * Date:  2020/1/14 9:35
 * Modified By:
 */
public class Zoo {
    public static String staticPk = staticPk();
    public String pk = pk();

    static {
        System.out.println("父类静态代码块!");
    }

    {
        System.out.println("父类非静态代码块");
    }

    public static String staticPk() {
        System.out.println("父类静态方法!");
        return "PK";
    };

    public  String pk() {
        System.out.println("父类普通方法!");
        return "PK";
    };

    public Zoo() {
       System.out.println("父类构造器");
    }
}
package com.fyqd.test.classload;

/**
 * Description:  big
 * Author: 程序猿学社
 * Date:  2020/1/14 9:35
 * Modified By:
 */
public class Pig extends  Zoo{
    public static String staticPk = staticPk();
    public String pk = pk();

    static {
        System.out.println("子类静态代码块!");
    }

    {
        System.out.println("子类非静态代码块");
    }

    public static String staticPk() {
        System.out.println("子类静态方法!");
        return "PK";
    };

    public  String pk() {
        System.out.println("子类普通方法!");
        return "PK";
    };

    public Pig() {
        System.out.println("子类构造器");
    }
}

测试类:

package com.fyqd.test.classload;

/**
 * Description:
 * Author: wude
 * Date:  2020/1/14 9:55
 * Modified By:
 */
public class Main {
    public static void main(String[] args) {
        Pig pig = new Pig();
    }
}

有一些社友反馈,社长之前出的题,太简单了,社长出了一道2星级别的题目,大家可以先不看答案,看看输出的控制台的结果是多少?能答对的社友,首先得恭喜下,从青铜,晋级到白银分段。

 


眼尖的社友,可能发现一个问题。
社长,社长,按你说的对象初始化顺序第三条,这里的打印应该是父类普通方法,父类非静态代码块才对。

 

社长跟大家说说,为什么会有这种问题出现?是谁在搞事情?

实际上是方法重写在搞事情,通过main方法,我们可以发现new的对象是子类,也就是说当前的this的指向就是子类。而这里本应该要调用父类的方法,由于被子类重写了,通过对象的多态性可知,这里打印的就是子类普通方法。

那些方法不能被重写?

final方法
静态方法
private修饰的方法。

难度3星 黄金段位

package com.fyqd.test.classload;

/**
 * Description:  pig
 * Author: 程序猿学社
 * Date:  2020/1/14 9:35
 * Modified By:
 */
public class Pig extends  Zoo{
    public static String staticPk = staticPk();
    public String pk = pk();

    static {
        System.out.println("子类静态代码块!");
    }

    {
        System.out.println("子类非静态代码块");
    }

    public static String staticPk() {
        System.out.println("子类静态方法!");
        return "PK";
    };
    @Override
    public  String pk() {
        System.out.println("子类普通方法!");
        return "PK";
    };

    public Pig() {
        System.out.println("子类构造器");
    }
}
package com.fyqd.test.classload;

/**
 * Description:动物园
 * Author: 程序猿学社
 * Date:  2020/1/14 9:35
 * Modified By:
 */
public class Zoo {
    public static String staticPk = staticPk();
    public String pk = pk();

    static {
        System.out.println("父类静态代码块!");
    }

    {
        System.out.println("父类非静态代码块");
    }

    public static String staticPk() {
        System.out.println("父类静态方法!");
        return "PK";
    };

    public  String pk() {
        System.out.println("父类普通方法!");
        return "PK";
    };

    public Zoo() {
       System.out.println("父类构造器");
    }
}
public class Main {
    public static void main(String[] args) {
        Pig pig = new Pig();
        System.out.println("---------");
        pig = new Pig();
    }
}

各位社友,再看看如上的代码,输出到控制台的结果应该是?

 

各位社友觉得这道理相对于前一道题,主要是考的那些方面?

实际上,就是考大家对类的初始化了解多少。实际上类初始化的时候,就会执行<clinit>方法,而<clinit>方法,就是通过静态代码块,静态变量,静态常量方法等组成。

博主,java小白,说说自己个人的一些见解,欢迎各位大佬指正!也可以在下方留言,大家进行一些技术交流。

每周实时更新,分享java最新大厂面试题,底层原理源码分析等干货
关注个人公众号“程序猿学社”或者扫码关注

发布了262 篇原创文章 · 获赞 360 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_16855077/article/details/103993794