final修饰静态变量和不修饰静态变量的区别

1 篇文章 0 订阅

今天听了B站的某教育平台的jvm课,记下笔记

看这段代码,输出是什么呢?

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

    class MyParent2{
         public static String str = "hello world";
         static{
             System.out.println("MyParent2 static block");
         }
    };

有开发经验的朋友基本都能知道结果。结果如下。

MyParent2 static block
hello world

原因是MyTest2类的main方法调用了Myparent2的静态变量str,从而导致Myparent2被初始化,类初始化过程中静态语句块先执行,所以程序打印了第一行 “MyParent2 static block”,接着打印了变量str “hello world“。

接着我们稍微改下代码,将MyParent2类的静态变量str,加上fianl修饰。

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

    class MyParent2{
         public final static String str = "hello world";
         static{
             System.out.println("MyParent2 static block");
         }
    };

打印结果是:

hello world

是的,没看错,只有一行hello world。并没有执行类MyParent2的静态语句块。这是为什么呢?

关键是final这个java关键字。大家知道被final修饰的变量,就是常量。而

在编译阶段,jvm发现某个变量被fianl修饰,即认定这个是常量,且这个常量在编译时就能确认其值。则把这个常量放到调用这个常量的方法的所在类的常量池中。本质上,并没有引用这个常量所在的类,因此并不会触发常量所在类的初始化,所以也不会打印这个类的静态语句块。

结合我们上面那个例子来理解:在程序编译阶段,jvm发现main方法中Myparent2.str是常量,则把这个常量也就是“hello world”放到自己也就是Mytest2的常量池中,运行阶段执行main方法的打印时,直接从自己的常量池中取出来就可以了,并不会涉及到Myparent2的初始化,所以Myparent2的静态语句块也就不会执行。

继续来看代码,稍做改动。将代码改为 public final static String str = System.currentTimeMillis()+"";

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

    class MyParent2{
         public final static String str = System.currentTimeMillis()+"";
         static{
             System.out.println("MyParent2 static block");
         }
    };

打印结果是:

MyParent2 static block
1581682607094

没错静态语句块又出现了,为什么?细心的同学肯定猜到了,看上面红色字体这句话

在编译阶段,jvm发现某个变量被fianl修饰,即认定这个是常量,且这个常量在编译时就能确认其值。。。

在比较下第二个例子和第三个例子不同的代码:

  1. 第二个例子是public final static String str = "hello world";
  2. 第三个例子是public final static String str = System.currentTimeMillis()+""

第二个例子中编译时就可以确定str肯定就是“hello world”,而第三个例子只有在运行期才能确定,所以肯定要将Myparent2初始化,静态语句块肯定就打印出来了

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值