JVM(5) --静态分配

本文深入探讨了静态分配的概念,解释了如何在编译阶段通过参数的静态类型决定方法的重载版本,展示了静态类型与实际类型的差异,以及它们在Java中的作用。

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

  下面的程序很好的演示了静态分配的含义(可以先试一下运行结果)

package....

/*静态方法分配(分配这个词并不好,因为dispatch并不运用到静态环境之中)演示*/

public class StaticTest{
    static abstract class Fruit{}
    static class Apple extends Fruit{}
    static class Orange extends Fruit{}

    public void eat(Fruit raw){
        System.out.println("Oh !!! Fruit is raw");
    }

    public void eat(Orange raw){
        System.out.println("Oh !!! Orange is raw");
    }
    public void eat(Apple raw){
        System.out.println("Oh !!! Apple is raw");
    }

    public static void main(string[] args){
        Fruit app = new Apple();
        Fruit oran = new Orange();
        StaticTest ts = new StaticTest();
        System.out.println(ts.eat(app));
        System.out.println(ts.eat(oran));
        
        
    }
    
}

   

    Fruit app = new Apple();

    其中的Fruit成为是静态类型(static Type),也叫外观类型,而Apple称为是变量的实际类型,静态类型的变化仅仅在使用过程中发生,变量本身的静态类型不会发生变化,并且最终静态类型是在编译期可知的。而实际类型变化的结果在运行期才可以确定,编译器在编译程序的时候并不知道一个对象的实际类型是什么

    在代码中,可以定义了两个静态类型相同,但实际类型不同的变量,但是编译器重载是通过参数的静态类型(上面说过实际类型运行期才可见),静态类型编译期是可知的,因此在编译阶段,javac编译器会根据参数的静态类型决定重载那个版本。

//运行结果

Oh!!! fruit is raw
Oh!!! fruit is raw

     所以由静态类型来定位方法执行版本的分派动作称为静态分配,静态分配发生在编译阶段,实际上是由编译器完成的,并不是由虚拟机完成。

 

### JVM 中 `<clinit>` 方法的含义及作用 在 Java 虚拟机(JVM)中,`<clinit>` 是一种特殊的类初始化方法。它是由编译器自动生成的方法,用于执行静态变量赋值语句以及静态代码块中的逻辑[^2]。 #### 静态初始化的过程 当一个类被加载到 JVM 后,在某些条件下会触发该类的初始化阶段。在这个阶段,JVM 会调用由编译器生成的 `<clinit>` 方法来完成以下任务: 1. **分配并设置静态变量初始值** 所有声明为 `static` 的成员会被赋予默认值(例如整数类型的静态变量会被设为0)。这是在内存分配期间自动完成的操作。 2. **执行显式的静态变量赋值操作** 如果开发者提供了具体的初始值给这些静态变量,则会在这一过程中将其更新至指定数值[^3]。 3. **运行静态代码块内的命令序列** 开发者可以在源文件里定义多个静态代码块;它们按书写顺序依次被执行一次,并且仅在此刻发生——即第一次主动使用某个特定类别之前立刻进行此类别的初始化动作。 需要注意的是,整个 `<clinit>` 过程遵循一定的规则和约束条件,比如它是线程安全的,意味着即使存在多条线程试图同时访问同一个尚未初始化过的类别时,也只会有一个实际进入其内部去履行必要的准备工作【^4】。 以下是展示如何通过反汇编工具观察到 `<clinit>` 方法的一个简单例子: ```java public class Example { static int x = 5; static final String CONSTANT = "Constant Value"; static { System.out.println("Static block executed"); } } ``` 如果对该类进行字节码析,可以看到类似于下面的内容片段表示了上述提到的各种行为组合而成的结果形式之一: ```text // Method descriptor #7 ()V // Stack: 2, Locals: 0 static {}; 0: getstatic #16 // Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #22 // String Static block executed 5: invokevirtual #24 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return Line numbers: [pc: 0, line: 5] Local variable table: (empty) ``` 此部代表的就是我们所讨论的那个隐含构造函数的具体实现细节的一部表现形态而已。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值