目录

    • 专栏导读
    • 一、类的加载与ClassLoader的理解
      • 1、加载
      • 2、链接
      • 3、初始化
    • 二、什么时候会发生类初始化
      • 1、类的主动引用(一定会发生类的初始化)
      • 2、类的被动调用(不会发生类的初始化)
    • 三、类加载器的作用
    • 四、动态创建对象执行方法
    • 五、成员初始化
    • 六、构造器初始化
    • 七、初始化顺序

专栏导读

🏆作者简介:哪吒,CSDN2022博客之星Top1、CSDN2021博客之星Top2、多届新星计划导师✌、博客专家💪,专注Java硬核干货分享,立志做到Java赛道全网Top N。

🏆姐妹篇,Java基础教程系列,目前已经700+订阅,CSDN最强Java专栏,包含全部Java基础知识点、Java8新特性、Java集合、Java多线程、Java代码实例,理论结合实战,实现Java的轻松学习。

🏆姐妹进阶篇,Java基础教程(进阶篇),包含Java高并发、Spring、MySQL等Java进阶技术栈。

🏆全部订阅后,可加入Java学习星球,完成Java从入门、实战、进阶全方位的Java知识体系学习。

🏆面试福音:10万字208道Java经典面试题总结(附答案)。

大家好,我是哪吒。

一、类的加载与ClassLoader的理解

1、加载

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后生成一个代表这个类的java.lang.class对象。

2、链接

将Java类的二进制代码合并到JVM的运行状态之中的过程。

  1. 验证:确保加载的类信息符合JVM规范,没有安全方面的问题;
  2. 准备:正式为类变量分配内存并设置类变量默认初始值的阶段,这些内存都将在方法区内进行分配;
  3. 解析:虚拟机常量池内的符号引用(常量名)替换为直接引用(地址)的过程。

3、初始化

  1. 执行类构造器()方法的过程。类构造器()方法是由编译期自动收集类中所有类变量的赋值动作和静态代码块中的语句合并产生的。(类构造器是构造类信息的,不是构造该类对象的构造器)。
  2. 当初始化一个类的时候,如果发现其父类还没有进行初始化,则需要先触发其父类的初始化。
  3. 虚拟机会保证一个类的()方法在多线程环境中被正确加锁和同步。

二、什么时候会发生类初始化

1、类的主动引用(一定会发生类的初始化)

  1. 当虚拟机启动,先初始化main方法所在的类;
  2. new一个类的对象; 调用类的静态成员(除了final常量)和静态方法;
  3. 使用java.lang.reflect包的方法对类进行反射调用;
  4. 当初始化一个类,如果其父类没有被初始化,则先会初始化它的父类;

2、类的被动调用(不会发生类的初始化)

  1. 当访问一个静态域时,只有真正声明这个域的类才会被初始化。如:当通过子类引用父类的静态变量,不会导致子类初始化;
  2. 通过数组定义类引用,不会触发此类的初始化;
  3. 引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了);

三、类加载器的作用

将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。

四、动态创建对象执行方法

package com.reflection;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
 
public class Test03 {
    public static void main(String[] args) throws Exception {
        //获得class对象
        Class c1 = Class.forName("com.reflection.User");
        //1、构造一个对象,本质是无参构造器
        User user1 = (User) c1.newInstance();
        System.out.println(user1);
 
        //2、通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(int.class, String.class, int.class);
        User user2 = (User) constructor.newInstance(1,"郭一诺",1);
        System.out.println(user2);
 
        //3、通过反射调用普通方法
        User user3 = (User) c1.newInstance();
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //invoke激活
        setName.invoke(user3,"素小暖");
        System.out.println(user3.getName());
 
        //4、通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");
        //true:取消Java语言访问检查
        name.setAccessible(true);
        name.set(user4,"素小暖2");
        System.out.println(user4.getName());
    }
}

五、成员初始化

成员变量可以在定义时进行初始化,也可以在构造函数中进行初始化。

如果没有进行初始化,则会自动赋予默认值:

  1. 对于基本数据类型的成员变量,其默认值为0(例如int、byte、float等)或false(例如boolean),而不是null。
  2. 对于引用类型的成员变量,其默认值为null。

在进行成员变量初始化时,可以使用赋值语句或代码块。

六、构造器初始化

在Java中,构造器是用于创建对象的特殊方法,在创建对象时会自动调用。在构造器中可以对对象进行初始化,包括成员变量和其他对象等。

如果没有定义构造器,则Java会自动提供一个默认构造器,其形式为无参构造器,并且不做任何初始化操作。如果需要进行初始化,则必须自定义构造器。

在定义构造器时,可以通过this关键字调用其他构造器来完成重载,也可以使用super关键字调用父类的构造器来进行初始化操作。

七、初始化顺序

Java中的对象在创建时会按照一定的顺序进行初始化,这个顺序通常是:

  1. 静态变量:首先被初始化,然后是类变量;
  2. 实例变量:接下来被初始化,最后是静态变量;
  3. 构造函数:被调用时,如果没有显式地调用构造函数,则会自动调用默认构造函数;

因此,在Java中,对象的初始化顺序是:静态变量、实例变量、构造函数。

🏆姐妹篇,Java基础教程系列,目前已经700+订阅,CSDN最强Java专栏,包含全部Java基础知识点、Java8新特性、Java集合、Java多线程、Java代码实例,理论结合实战,实现Java的轻松学习。

🏆姐妹进阶篇,Java基础教程(进阶篇),包含Java高并发、Spring、MySQL等Java进阶技术栈。

🏆全部订阅后,可加入Java学习星球,完成Java从入门、实战、进阶全方位的Java知识体系学习。

更多推荐

49天精通Java,第17天,Java类加载与初始化