JavaSE面试题——类初始化 & 实例初始化

简介: JavaSE面试题——类初始化 & 实例初始化

1.Go!!!


以下代码的运行结果是:👇👇👇


运行结果如下:👇👇👇

分析:


1.    首先这道题它考查了:类的初始化、实例的初始化、方法重写、对象的多态性这些内容。

2.    类的初始化:

·       一个类要创建实例需要先加载并初始化该类(main方法所在的类要先进行加载和初始化)。

·       一个子类要加载并初始化,需要先加载并初始化它的父类。

·       一个类的初始化就是执行<clinit>()方法,<clinit>()方法由静态类变量显示赋值代码和静态代码块组成,同时<clinit>()方法只会执行一次,而静态类变量显示赋值代码和静态代码块的执行顺序是从上到下顺序执行(谁在前面先执行谁)。

     3. 实例初始化:

·       实例初始化就是执行<init>()方法,<init>()方法可能重载有多个,有几个构造器就有几个<init>()方法。

·       <init>()方法由非静态(实例变量)显示赋值代码和非静态代码块、对应的构造器组成。它们三者的执行顺序是:非静态(实例变量)显示赋值代码和非静态代码块从上到下顺序执行(谁在前面先执行谁),而对应的构造器则在最后执行。

·       每次创建实例对象,调用对应构造器,执行的就是对应的<init>方法。

·       <init>方法的首行是 super() super(实参列表),即对应会先执行父类的<init>方法。

      4.哪些方法不可以被重写?

·       final修饰的方法、静态方法、private等子类中不可见的方法。

      5.对象的多态性

·       子类如果重写了父类的某个方法,通过子类对象调用的一定是子类重写过的方法。

·       非静态方法默认的调用对象是 this

·       this对象在构造器或者说<init>方法中就是正在创建的对象。

public class Father {
    private int i = test();
    private static int j = method();
    static {
        System.out.print("(1)");
    }
    Father() {
        System.out.print("(2)");
    }
    {
        System.out.print("(3)");
    }
    public int test() {
        System.out.print("(4)");
        return 1;
    }
    public static int method() {
        System.out.print("(5)");
        return 1;
    }
}
public class Son extends Father {
    private int i = test();
    private static int j = method();
    static {
        System.out.print("(6)");
    }
    Son() {
        System.out.print("(7)");
    }
    {
        System.out.print("(8)");
    }
    public int test() {
        System.out.print("(9)");
        return 1;
    }
    public static int method() {
        System.out.print("(10)");
        return 1;
    }
    //main方法所在的类需要先加载和初始化
    public static void main(String[] args) {
        Son s1 = new Son();
        System.out.println();
        Son s2 = new Son();
    }
}

这里先进行的是类初始化过程。

因为main方法在Son子类中,所以这里会先进行Son类的加载和初始化,而Son有一个父类Father,所以这里先对Father类进行加载和初始化。

先去执行Father类中的静态类变量显示赋值代码和静态代码块,因为静态类变量显示赋值代码 private static int j = method();位置更靠前,所以它先执行,而静态方法是不能被重写的,所以这里执行父类自己的method方法,首先输出(5)。然后继续执行父类的静态代码块,输出(1)。到此,父类的加载和初始化完成,转回子类进行加载和初始化。那么同父类一样,因为静态类变量显示赋值代码 private static int j = method();位置更靠前,所以它先执行,输出(10)。然后执行子类的静态代码块,输出(6)。即类初始化全部完成,目前输出了 (5)(1)(10)(6)


下面进行实例初始化过程。


因为<init>()方法的首行是 super(),所以此时仍然是先到父类中进行实例初始化:非静态(实例变量)显示赋值代码和非静态代码块,而非静态(实例变量)显示赋值代码位置更靠前,private int i = test();它先执行,而在非静态方法里面都有一个默认的对象this表示当前正在创建的对象,因为第一次实例初始化过程是由main方法中的 Son s1 = new Son(); 走过来的,所以当前this对象指的就是Son对象,也就是执行的其实应该是子类重写之后的test方法,即输出(9)。然后继续执行父类的非静态代码块,输出(3)。最后执行父类的无参构造,输出(2)。到此,父类的实例初始化完成,转回子类进行实例初始化。同父类一样,因为非静态(实例变量)显示赋值代码位置更靠前,private int i = test();它先执行,输出(9)。然后执行子类的非静态代码块,输出(8)。最后执行子类的无参构造,输出(7)。即目前输出了 (5)(1)(10)(6)(9)(3)(2)(9)(8)(7)


main中还有最后两行需要执行:System.out.println();   Son s2 = new Son();

首先打印一个换行,然后Sonnew了第二个对象,要进行了第二次实例初始化(类初始化只会进行一次),所以类初始化相关的静态类变量显示赋值代码和静态代码块不会再执行了,只会执行非静态(实例变量)显示赋值代码和非静态代码块。那么同上面分析的一样,先去父类进行实例初始化、然后回到子类进行实例初始化。最终第二次实例初始化完成:(9)(3)(2)(9)(8)(7)


即最终的结果就是:👇👇👇

(5)(1)(10)(6)(9)(3)(2)(9)(8)(7)

(9)(3)(2)(9)(8)(7)

相关文章
|
12天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
53 4
|
2月前
|
安全 Java 应用服务中间件
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
什么是类加载器,类加载器有哪些;什么是双亲委派模型,JVM为什么采用双亲委派机制,打破双亲委派机制;类装载的执行过程
JVM常见面试题(三):类加载器,双亲委派模型,类装载的执行过程
|
1月前
|
JSON 调度 数据库
Android面试之5个Kotlin深度面试题:协程、密封类和高阶函数
本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点。文章详细解析了Kotlin中的协程、扩展函数、高阶函数、密封类及`inline`和`reified`关键字在Android开发中的应用,帮助读者更好地理解和使用这些特性。
20 1
|
3月前
|
Java
【Java集合类面试三十】、BlockingQueue中有哪些方法,为什么这样设计?
BlockingQueue设计了四组不同行为方式的方法用于插入、移除和检查元素,以适应不同的业务场景,包括抛异常、返回特定值、阻塞等待和超时等待,以实现高效的线程间通信。
【多线程面试题 二】、 说说Thread类的常用方法
Thread类的常用方法包括构造方法(如Thread()、Thread(Runnable target)等)、静态方法(如currentThread()、sleep(long millis)、yield()等)和实例方法(如getId()、getName()、interrupt()、join()等),用于线程的创建、控制和管理。
|
3月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
10天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
12天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
37 4
|
1月前
|
算法 Java 数据中心
探讨面试常见问题雪花算法、时钟回拨问题,java中优雅的实现方式
【10月更文挑战第2天】在大数据量系统中,分布式ID生成是一个关键问题。为了保证在分布式环境下生成的ID唯一、有序且高效,业界提出了多种解决方案,其中雪花算法(Snowflake Algorithm)是一种广泛应用的分布式ID生成算法。本文将详细介绍雪花算法的原理、实现及其处理时钟回拨问题的方法,并提供Java代码示例。
67 2
|
1月前
|
JSON 安全 前端开发
第二次面试总结 - 宏汉科技 - Java后端开发
本文是作者对宏汉科技Java后端开发岗位的第二次面试总结,面试结果不理想,主要原因是Java基础知识掌握不牢固,文章详细列出了面试中被问到的技术问题及答案,包括字符串相关函数、抽象类与接口的区别、Java创建线程池的方式、回调函数、函数式接口、反射以及Java中的集合等。
28 0