类以及类实例的初始化

本文详细介绍了Java中类和接口的初始化过程,包括主动使用与被动使用的区别,以及类实例的初始化流程。通过具体示例解释了类加载时机及初始化顺序。

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

 
类初始化
每个类或者接口必须在首次使用时初始化。java虚拟机会在6种情况下初始化一个类对象,这六种情况称为主动使用,分别是:
l         创建类的新实例
l         调用类中声明的静态方法
l         操作类或接口中声明的非常量静态字段
l         调用Java API中特定的反射方法
l         初始化一个类的子类
l         制定一个类作为Java虚拟机启动时的初始化类
任何一个类的初始化都要求它的所有祖先类(非祖先接口)预先被初始化,而接口的初始化则不需要祖先接口预先被初始化。
 
初始化一个类包含两个步骤:
1.如果类存在直接超类的话,且直接超类还没有被初始化,就先初始化直接超类
2.如果类存在一个初始化方法,就执行此方法
 
接口初始化只需一个步骤:
如果该接口存在一个初始化方法的话,就执行此方法
 
被动使用
       使用一个非常量的静态字段(方法)只有当类或者接口的确声明了这个字段(方法)时才是主动使用。比如,class A中有个非常量静态字段x,class B继承A,那么当使用B.x的时候,不会初始化B类,只会初始化A类
       如果一个字段既是static的,又是final的,并且使用一个编译时常量表达式初始化,是用这样的字段,就不是对声明该字段的类的主动使用。
 
类实例的初始化
       针对源代码中的每一个类的构造方法,java编译器都产生一个<init>方法。如果类没有明确地声明任何构造方法,编译器默认产生一个无参数的构造方法,该方法仅仅调用超类的无参数构造方法。
       如果构造方法通过明确地调用同一个类中的另一个构造方法开始(通过this),那么对应的<init>方法由两部分组成:
l         一个同类的<init>方法的调用
l         实现了对应构造方法的方法体的字节码(即对应的构造方法的代码)
 
       如果构造方法不是通过一个this调用开始的,且这个对象不是Object,<init>方法则由三部分组成
l         一个超类的<init>方法的调用
l         任意实例变量初始化方法的字节马(包括定义成员变量的时候赋的初值,还有初始化块)
l         实现了对应构造方法的方法体的字节码(即对应的构造方法的代码)
 
       在调用<init>之前,虚拟机为新的对象准备好了堆内存,并把实例变量初始化为默认初始值。
 
public class Test {
    
        
static String a = "string-a";
        
static String b;
    
        String c 
= "stirng-c";
        String d;
        
        
static String e = getStaticString("string-e");
        
        
static {
            printStatic(
"before static");
            b 
= "string-b";
            printStatic(
"after static");
        }
        
        
static String f = getStaticString("string-f");
        
        
public static String getStaticString(String s)
        {
            System.out.println(
"getStaticString(" + s + ")");
            
return s;
        }
        
        
public String getString(String s)
        {
            System.out.println(
"getString(" + s + ")");
            
return s;
        }
    
        String g 
= getString("string-g");
        
        {
            System.out.println(
"before {");
            g 
= getString("string-g-new");
            System.out.println(
"after }");
        }
        
        String h 
= getString("string-h");
        
        
public static void printStatic(String title) {
            System.out.println(
"---------" + title + "---------");
            System.out.println(
"a = "" + a + """);
            System.out.println(
"b = "" + b + """);
        }
    
        
public Test() {
            print(
"before constructor");
            d 
= "string-d";
            print(
"after constructor");
        }
    
        
public void print(String title) {
            System.out.println(
"---------" + title + "---------");
            System.out.println(
"a = "" + a + """);
            System.out.println(
"b = "" + b + """);
            System.out.println(
"c = "" + c + """);
            System.out.println(
"d = "" + d + """);
        }
    
        
public static void main(String[] args) {
           
new Test();
           TT.f();
        }
    
    }

class T
{
    
static void f()
    {
        System.out.println(
"static void f()");
    }
    
static
    {
        System.out.println(
"T is inited");
    }
}

class TT extends T
{
    
static
    {
        System.out.println(
"TT is inited");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值