【JVM虚拟机】类的加载之常量池

本文围绕JVM展开,解释了在JVM中静态变量会存在于调用该静态变量的方法所属类的变量池中,还介绍了常量是被final修饰、值不可变的变量,能保存到常量池的值须被final修饰。此外,说明了Java中部分基本类型包装类实现常量池技术的情况,以及String类型会扩展变量池。

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

在上一章的使用 步骤,在"访问某个类或者接口的静态变量 " 这一步骤留下一个疑问?为什么是加载MyParent类呢? 下面我们来说说倒是为什么?

我们先写个例子:

public class Test1 {

    public static void main(String[] args) {
        System.out.println(MyParent.str);
    }

    public static class MyParent {

        public static final int str = 123;

        public MyParent(){
            System.out.println("MyParent inited");
        }
    }
}

然后我们运行,发现控制台只打印了 123 ,并没有打印MyParent inited ,这是为什么呢?

其实在JVM中,静态变量会存在于调用该静态变量的方法所属的类的变量池中

这句话听起来是很绕口,我们把他带到刚才的例子中解释一遍

就是调用MyParent.str 静态变量的main方法,main方法所属的Test1 这个类中的变量池中

其实就是在jvm加载的过程中,会把MyParent.str 这个变量保存到Test1 这个类中。

验证方式:

  1. 通过Javap来解析下
    在这里插入图片描述
    发现编译的时候,已经把变量123加载进来了。

  2. MyParent 编译的class文件删除,再次执行
    在这里插入图片描述
    删除后,再次执行main方法,会发现可以正常使用。说明已经加载到Test1

什么是常量呢?

常量是指被final修饰的变量,值一旦确定就无法改变。

final可以修饰静态变量、实例变量和局部变量。

所以,能保存到常量池中的值,必须是被final 修饰的 变量。

哪些类型支持哪些常量池呢?

Java中八种基本类型的包装类的大部分都实现了常量池技术,它们是Byte、Short、Integer、Long、Character、Boolean,另外两种浮点数类型的包装类(Float、Double)则没有实现。另外Byte,Short,Integer,Long,Character这5种整型的包装类也只是在对应值在-128到127时才可使用对象池。

String 类型的intern()

String类型的intern() 会扩展变量池。如下面的例子

public static void main(String[] args) {
        String s0 = "xyz";
        String s1 = new String("xyz");
        
        System.out.println(s0 == s1); //false
       
        String intern = s1.intern();
        System.out.println(s0 == intern);//true  

    }

为什么调用intern() 后,再比较会相同呢?

因为在调用intern()后,会先看看常量池中是否存在“xyz”这个值,如果不存在就保存,并且返回,如果存在,就直接获取并且返回。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值