当类被加载时,类的静态代码块不一定被加载解析

本文详细探讨了Java中的类加载机制,特别是双亲委派模型,以及在类加载过程中静态代码块的执行条件。通过示例代码展示了如何在特定情况下静态代码块可能不会执行。同时,文章列举了类加载时不会触发初始化的三种情况,并总结了类加载和初始化的顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抄?你也要解决下问题呀。都tm的照搬

网上对这个问题没有一个人讲的清楚,还都是抄别人的,十篇文章都是抄的一个人,还讲的不清楚。哎,世风日下。



在这里插入图片描述

一、类加载定义

java编译器将 .java 文件编译成扩展名为 .class 的文件也就是字节码文件。.class 文件中保存着java转换后,虚拟机将要执行的指令。当需要某个类的时候,java虚拟机会加载 .class 文件,并创建对应的class对象,将class文件加载到虚拟机的内存,这个过程被称为类的加载。

二、类加载过程中用到了双亲委派模型

简单来说就是:在类加载的时候总会找他的爸爸,从最基础的类开始慢慢加载。

在这里插入图片描述
当一个非顶层类加载器收到了类加载的请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(它的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载。

2.补充完一丢丢基础,再来讨论一下类的加载中,静态代码块一定会被执行吗?答案:不一定

代码如下(示例):

package com.rufeng.study.rufeng.util;

import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer;

import java.util.HashMap;
import java.util.Map;
/**
 * @author rufeng
 * @date 2021/3/8 11:55 
 */
class B extends TestSuan {
    public static int anInt =1;
    static {
        System.out.println("B1");
    }

    {
        System.out.println("B2");
    }
}

public class TestSuan {
    public static int p =2;
    static {
        System.out.println("A1");
    }

    {
        System.out.println("A2");
    }

    public static String VALUE = "static value loading";

    public static final String FIANL_VALUE = "fianl value loading";

    public static void main(String[] args) {
        System.out.println(B.p);

运行结果
在这里插入图片描述

此处可以看到类B已经加载,但是静态代码块没有被加载。这里要说一下被动引用的问题。当类加载出现一下几种情况是加载类的时候不会初始化的(这句话如果有不严谨的,请大佬指出)。

1、通过子类引用父类的静态字段或者父类特有静态方法,不会导致子类初始化(子类是否会进行加载、连接等过程取决于虚拟机的参数设置)。
2、通过数组定义来引用类,不会触发此类的初始化。

3、调用类B使用类A的常量变量时,不会触发常量所在的类A的初始化,A类的常量在编译阶段会存入调用类B的常量池中,类B看起来是访问类A的常量,实际上是在自身的常量池(B类的常量池)中访问该常量,所以此时类B的静态代码块不会被加载。

总结

简单的加载顺序可以理解为(特殊情况特殊对待)

1、先执行父类静态代码块,父类静态成员变量 (代码先后顺序执行);
2、再执行子类静态代码块,子类静态成员变量(代码先后顺序执行);
3、再执行父类方法块(方法块与静态方法块的区别是方法块属于对象而不是类本身);
4、再执行父类构造器完成父类对象实例化;
5、再执行子类方法块;
6、最后执行子类构造器,完成子类对象实例化。
(重点注意: 子类静态方法以及父类静态方法的执行顺序是怎样往往取决于你在哪里调用该方法。)
7、若你在对象实例化之前,用父类进行调用静态方法,则它出现在父类静态代码块之后(因为只有完成了类加载之后,才能调用静态方法)。
8、若你在对象实例化之前,用子类进行调用静态方法,则出现在子类静态代码块之后(加载子类,必须加载父类,那父类静态代码块先执行,子类代码块后执行,完成加载再执行子类静态方法)。
9、若在对象实例化之后,则该静态函数调用会发生在对象构造方法执行之后。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值