JVM类加载解析阶段 父类和子类静态方法、私有方法、final修饰方法调用

本文探讨了JVM类加载的静态解析阶段,解释了静态字段与静态方法、私有方法及final修饰方法的加载过程。通过代码示例展示了静态方法与私有方法因特性不同,在解析阶段即确定唯一调用版本,而final方法因不可被覆盖,也在解析阶段固定调用。

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

首先先说明下基本概念,

  • 静态解析:符号引用在类加载阶段就转为直接引用,编译期可知,运行期不可变。
  • 动态连接:符号引用在运行期间转化为直接引用。

下面,看下这段代码的输出结果,代码一

public class Animal {

    static {
        System.out.println("static Animal");
    }

    public static int value = 1;

    public Animal() {
        System.out.println("构造方法 Animal");
    }

    public static void main(String[] args) {
       int value = Dog.value;
    }


public class Dog extends Animal {

    static {
        System.out.println("static Dog");
    }


    public Dog() {
        System.out.println("构造方法 Dog");
    }
}

输出结果:

static Animal

原因分析,对于静态字段,只有直接定义这个字段的类才会被初始化,类初始化阶段是执行类构造器clinit()方法的过程,clinit()是由编译器自动收集类中的所有类变量的赋值动作和静态语句块中的语句合并产生的。

没有回答对的,要认真看下面的内容啦,思考下这段代码的输出结果,

public class Animal {

    public Animal() {
        System.out.println("构造方法 Animal");
    }


    public static void sleep() {
        System.out.println("animal sleep");
    }


    private void hit() {
        System.out.println("animal hit");
    }


    public final void hello() {
        System.out.println("animal hello");
    }

   
    public static void main(String[] args) {
        Animal animal = new Dog();

        animal.sleep();
        animal.hit();
        animal.hello();
    }


public class Dog extends Animal {

    public Dog() {
        System.out.println("构造方法 Dog");
    }


    public static void sleep() {
        System.out.println("dog sleep");
    }

    private void hit() {
        System.out.println("dog hit");
    }
    
	 public final void hello() {
        System.out.println("dog hello");
    }
}

先想下这段代码可以正常执行吗,这段代码是不能正常执行的,在子类被final修饰的hello()会有编译错误的问题,这里又可以引申一个新的概念了,父类中被final修饰的方法是不能被重写的

 public final void hello() {
        System.out.println("dog hello");
    }

我们把这个编译错误的代码注释掉,思考下这个时候的输出结果,结果见下,

构造方法 Animal
构造方法 Dog
animal sleep
animal hit

sleep和hit方法全部调用的都是父类的。为什么呢?
sleep方法是静态方法,hit方法是私有方法,这两种方法各自的特点决定了他们都不可能通过继承或别的方式重写其他版本,因此他们在类加载中的解析阶段就有了可确定的调用版本,在运行期是不可变的。

  • 静态方法与类型直接关联
  • 私有方法在外部不可被访问

从JVM的角度来说,只要能被invokestatic和invokespecial指令调用的方法,都可以在解析阶段确定唯一的调用版本。

总结,以下方法可以在解析阶段确定调用版本:

  • 静态方法
  • 私有方法
  • 实例构造器
  • final修饰的方法,无法被覆盖
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值