V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
reid2017
V2EX  ›  Java

请教关于 final 的疑问

  •  
  •   reid2017 · 2019-01-18 15:34:44 +08:00 · 2695 次点击
    这是一个创建于 2141 天前的主题,其中的信息可能已经有所发展或是发生改变。

    经常阅览一些大神写的开源项目,看到很多在定义引用类型 /对象变量时,都会加上 final 关键字约束,很多方法的形参如果是引用类型也会加上 final,查阅资料是不让改变引用的指向,据说会对 jvm 性能有一定的提升。

    不知道有没有大神详细解答下,用或不用 final ,性能差别会有多大呢?或者与性能无关,而是其它的原因?

    14 条回复    2019-01-19 12:47:08 +08:00
    Hyseen
        1
    Hyseen  
       2019-01-18 15:39:59 +08:00   ❤️ 1
    不会有性能上的提升,参考知乎上 R 大的回答。
    https://www.zhihu.com/question/66083114/answer/242241071
    earendil1412
        2
    earendil1412  
       2019-01-18 15:44:08 +08:00 via Android
    class 上是防止被继承
    方法上是防止被 override
    这俩的原因是因为:要设计一个好的可继承类其实是很麻烦的。具体去参考下 oo 设计的东西
    field 和内部变量上用是防止引用被修改了。一定程度上可以防止自己写 bug 以及类在别的地方被修改了。
    chenyu8674
        3
    chenyu8674  
       2019-01-18 15:56:25 +08:00
    任何技术 /方案 /架构 /框架都离不开两个命题:提升 NBer 的体验和降低 SBer 的破坏力
    final 是后者
    reid2017
        4
    reid2017  
    OP
       2019-01-18 16:43:31 +08:00
    @google614
    @earendil1412
    @chenyu8674
    所以,大佬们平常写代码,会习惯性的加 final 修饰局部变量(引用类型)吗?
    earendil1412
        5
    earendil1412  
       2019-01-18 17:01:41 +08:00 via Android
    @reid2017 好吧,我习惯不太好。。。
    42alex
        6
    42alex  
       2019-01-18 17:02:28 +08:00   ❤️ 1
    编译器会把 final 改为内嵌调用,性能还会降低一些,加 final 主要是为了防止被覆盖
    passerbytiny
        7
    passerbytiny  
       2019-01-18 17:02:40 +08:00
    final 别乱搞用,都加 final,那是搬石头砸自己。给变量或形参加上 final,基本表示接下来准备弄它了,加上 final 限制,能避免一不小心让它被替身代替了。如果有良好的代码规范和代码评审,那么加不加 final 都无所谓,因为一个方法就几十行,误重新赋值的可能性太低了。

    有些变量是要根据不同的条件设置不同的值的,这时候你要是上了 final,绝对编译错误。
    zn
        8
    zn  
       2019-01-18 17:16:29 +08:00 via iPhone
    @passerbytiny final 局部变量只可以赋值一次吗,不同条件下赋值一次就好了,依然可以用 final
    earendil1412
        9
    earendil1412  
       2019-01-18 18:14:20 +08:00 via Android
    @42alex java 8 会自动给能加 final 的内部变量加上 final。
    reid2017
        10
    reid2017  
    OP
       2019-01-18 18:39:33 +08:00
    @earendil1412 还有这种操作?
    earendil1412
        11
    earendil1412  
       2019-01-18 18:53:24 +08:00 via Android
    @reid2017 为了兼容λ。λ里的变量只允许 final 的。
    DovaKeen
        12
    DovaKeen  
       2019-01-18 21:33:12 +08:00
    我听过一句话叫一个类要不就是面向继承的,要不就是 final 修饰的。结合开闭原则来看,如果有不想被子类修改的方法,用 final 修饰一下还是挺好的。
    honeycomb
        13
    honeycomb  
       2019-01-19 12:06:18 +08:00 via Android
    @reid2017 写 final 不是为了性能,而是为了功能。
    很早期的 JVM 或许会有性能上的差异,现在都 9102 年了。
    liangdu
        14
    liangdu  
       2019-01-19 12:47:08 +08:00 via Android
    在编译后会加入内存屏障,保证多线程的可见性(你猜对了,他这个功能和 volatile 一样。所以 JVM 规范声明了两者只能选其一),以及导致初始化过程中被多线程访问时出现逃逸(没初始化就被访问了,遵循 happenbefores 原则)。和 final static 一起使用可以让初始化在编译期可以变成 constant value。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5842 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 148ms · UTC 01:46 · PVG 09:46 · LAX 17:46 · JFK 20:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.