Java中静态常量和静态变量的区别

在jvm参数当中一共有以下三种

  • -XX:+ 加号表示开启选项
  • -XX:- 减号表示关闭选项
  • -XX:=:表示将option的值设置为value
  • 在idea中添加vm option参数,–XX:+TraceClassLoading用于打印类加载信息

如下:

测试java中静态常量和静态变量区别的样例,表明两者加载时的区别。

StaticClass类中定义了静态常量FIANL_VALUE和静态变量VALUE,静态代码块的打印语句表示类被加载:

public class StaticClass {  

    static {  
        System.out.println("StaticClass loading...");  
    }  
      
    public static String VALUE = "static value loading";  
      
    public static final String FIANL_VALUE = "fianl value loading";  
}  


StaticClassLoadTest类用于测试静态变量的加载:

public class StaticClassLoadTest {

    public static void main(String[] args) {
        System.out.println("StaticClassLoadTest...");
        printStatic();
        //printnewStatic();
    }

    private static void printStatic() {
        System.out.println(StaticClass.FIANL_VALUE);
        System.out.println(StaticClass.VALUE);

    }

    private static void printnewStatic() {
        System.out.println(StaticClass.FINAL_VALUE_STR);
        System.out.println(StaticClass.VALUE);
    }


}
输出:

[Loaded java.net.InetAddress$Cache$Type from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddressImplFactory from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClassLoadTest from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddressImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet6AddressImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded sun.net.spi.nameservice.NameService from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.InetAddress$2 from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClassLoadTest...
fianl value loading
[Loaded sun.net.util.IPAddressUtil from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet4Address from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksConsts from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClass from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded java.net.SocketOptions from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClass loading...
[Loaded java.net.SocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
static value loading

输出显示在打印静态常量时,StaticClass类没有被加载,在输出静态变量的前才打印类加载信息。这表明类的未加载的情况下也能引用其静态常量信息,原因是因为常量值存储在JVM内存中的常量区中,在类不加载时即可访问。

注:经过编译优化,静态常量 FIANL_VALUE 已经存到NotInit类自身常量池中,不会加载StaticClass  

但是不能说所有的静态常用访问都不需要类的加载,这里还要判断这个常量是否属于“编译期常量”,即在编译期即可确定常量值。如果常量值必须在运行时才能确定,如常量值是一个随机值,也会引起类的加载,如下:

    public static final StringBuilder FINAL_VALUE_STR = new StringBuilder("new fianl value loading");

输出: 

[Loaded com.xxx.domain.StaticClassLoadTest from file:/D:/work/fix/xxx.ui/target/classes/]
[Loaded sun.net.util.IPAddressUtil from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.Inet4Address from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded sun.launcher.LauncherHelper$FXHelper from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.lang.Class$MethodArray from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksConsts from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
StaticClassLoadTest...
[Loaded java.net.SocketOptions from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.AbstractPlainSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.PlainSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.SocksSocketImpl from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded java.net.AbstractPlainSocketImpl$1 from C:\Program Files\Java\jdk1.8.0_25\jre\lib\rt.jar]
[Loaded com.xxx.domain.StaticClass from file:/D:/work/fix/xxx.ui/target/classes/]
StaticClass loading...
new fianl value loading
static value loading

总结:

final修饰的实例属性,在实例创建的时候才会赋值。

static修饰的类属性,在类加载的准备阶段赋初值,初始化阶段赋值。

static+final修饰的String类型或者基本类型常量,JVM规范是在初始化阶段赋值,但是HotSpot VM直接在准备阶段就赋值了。

static+final修饰的其他引用类型常量,赋值步骤和第二点的流程是一样的。

参考:你知道Java中final和static修饰的变量是在什么时候赋值的吗?_CoderW喜欢写博客的博客-CSDN博客
 

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值