final 这道送分题,你答对了吗?

Photo By Instagram ro.junghwa

   

上期问题

你用过 Java 中的 final 关键字吗?它有哪些作用?这也是出镜率极高的题目哦。

我的答案

1. final 修饰类的时候代表这个类是不可以被扩展继承的,例如 JDK 里面的 String 类。

2. final 修饰方法的时候代表这个方法不能被子类重写。

3. final 修饰变量的时候代表这个变量一旦被赋值就不能再次被赋值。

想必上面这三点是大家所熟知的,但是下面这 2 点你想到了吗?


缓存

final 变量会被缓存在寄存器中而不需要去主从获取,而非 final 变量的则需要去主存重新加载。

线程可见性

类的 final 域在编译器层面会保证在类的构造器结束之前一定要初始化完成,同时 Java 内存模型会保证对象实例化后它的 final 域对其他线程是可见的,然而非 final 域并没有这种待遇。例如如下代码:

public class FinalFiled {
    final int x;
    int y;
    static FinalFiled f;


    public FinalFiled() {
        x = 100;
        y = 100;
    }


    static void writer() {
        f = new FinalFiled();
    }


    static void reader() {
        if (f != null) {
            int i = f.x;  // 保证此时一定是 100
            int j = f.y;  // 有可能此时还是 0
        }
    }
}

当线程 A 执行了 writer 方法后,有线程 B 会进入 f != null 成立条件的代码块,此时由于变量 x 是 final 修饰的,JMM 会保证 x 此时的值一定是 100,而 y 是非 final 的,则有可能此时 y 的值还是 0,并未被初始化。

安全性

String 类的安全性也得益于恰到好处的使用了大量的 final 域,大家可以去翻翻 String 类的源码。我们来举个例子,假设有线程 A 执行如下代码段:

Global.flag = "/001/002".substring(4);

又有线程 B 执行如下代码段:

String myS = Global.flag;
if (myS.equals("/001"))System.out.println(myS);

如果没有 final 域的可见性保证,那么线程 B 在执行的时候有可能看到的字符串的长度可能仍然是 0。当有了 final 域的可见性保证,就可以让并发程序正确的执行。也使得 String 类成为名副其实不可变安全类。

最后插播一个问题,今天有位读者私信毛毛虫说,可不可以把背景图换成和文章内容相关的图?不知道其他朋友们有没有类似的想法?

毛毛虫自己的想法有 2 点,第 1 点是觉得美美图好看,文章过来就很想多看几眼,嘿嘿;第 2 点是其实咱们都是技术文章,每篇都找和内容相关的背景图还挺不好找的,当然啦如果大多数朋友都不喜欢看妹子图,我们就去掉妹子图啦。

欢迎的大家把自己的想法告诉毛毛虫,让毛毛虫和朋友们的地盘变得更加美好。

以上即为昨天的问题的答案,小伙伴们对这个答案是否满意呢?欢迎留言和我讨论。

又要到年末了,你是不是又悄咪咪的开始看机会啦。为了广大小伙伴能充足电量,能顺利通过 BAT 的面试官无情三连炮,我特意推出大型刷题节目。每天一道题目,第二天给答案,前一天给小伙伴们独立思考的机会。

点下“在看”,鼓励一下?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值