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

什么情况下, Java 的形参推荐使用 final 修饰

  •  
  •   brucefu · 2020-08-17 10:50:34 +08:00 · 4177 次点击
    这是一个创建于 1563 天前的主题,其中的信息可能已经有所发展或是发生改变。

    好多情况下都可以使用 final 修饰 但是修饰多了,好啰嗦,不美观 什么情况下使用 final 修饰形参既实用又美观

    21 条回复    2020-09-01 12:16:39 +08:00
    securityCoding
        1
    securityCoding  
       2020-08-17 10:51:06 +08:00
    不可变
    Jooooooooo
        2
    Jooooooooo  
       2020-08-17 10:54:01 +08:00
    遵守其语义就行

    用 final 表达这个东西引用不可变 (但很多时候想表达其中内容也不可变, final 很不幸做不到这一点, 不过这是另外一回事
    qwerthhusn
        3
    qwerthhusn  
       2020-08-17 10:55:10 +08:00
    对于代码块中的变量,可以直接弃用 final 了
    qwerthhusn
        4
    qwerthhusn  
       2020-08-17 10:56:44 +08:00
    java 8 之后,即使不用 final,也可以将变量传入到匿名内部类或者 lambda 里面去(编译器会自动检测这个变量有没有改动赋值,如果没有,就默认是 final 的了)
    sagaxu
        5
    sagaxu  
       2020-08-17 11:13:34 +08:00 via Android
    多线程并发的时候就有区别了,final 修饰影响并发时的语义
    Goooler
        6
    Goooler  
       2020-08-17 11:28:39 +08:00
    直接用 kotlin 就好了,不用写
    OysterQAQ
        7
    OysterQAQ  
       2020-08-17 11:46:20 +08:00
    在这个变量不变化 却又参与循环的时候 最好用 final 修饰 表明市常量 性能会有较大提升
    talen666
        8
    talen666  
       2020-08-17 11:53:41 +08:00
    建议严谨点,就像 public private 很多时候用哪个也不影响运行。
    340244120w
        9
    340244120w  
       2020-08-17 12:00:15 +08:00 via iPhone
    对不变的数字和字符串加上,可以在编译时完成常量替换,省去运行时的计算或字符串拼接
    ZeawinL
        10
    ZeawinL  
       2020-08-17 12:39:48 +08:00 via iPhone
    自定义 HashMap 等容器的 key 时
    aguesuka
        11
    aguesuka  
       2020-08-17 12:43:51 +08:00 via Android
    java8 以后,除了自注释,任何情况都不要写。只要变量没有变化过就是 final 的。
    MakHoCheung
        12
    MakHoCheung  
       2020-08-17 12:55:07 +08:00 via iPhone
    @aguesuka 这是真的吗,是在编译过程优化的?我一直以为是在 lamda 里面才自动变 final
    zlllllei
        13
    zlllllei  
       2020-08-17 13:30:41 +08:00
    @qwerthhusn 不知道是不是 eclipse 的坑,在方法内对一个变量重新赋值后,再在 lambda 中使用会提示非 final 的错误,你把对这个变量的赋值语句放到一个方法内就没问题,例如 i = 1; i=2; item -> item.id != i; 这里 i 就会报错。 你改成 i = getI(); 就没问题了。
    kappa
        14
    kappa  
       2020-08-17 13:38:37 +08:00
    @MakHoCheung google "effectively final"
    rockyou12
        15
    rockyou12  
       2020-08-17 13:39:59 +08:00
    所以像 kotlin 和其它语言中的 var 和 val 就很方便能区别可不可变
    MakHoCheung
        16
    MakHoCheung  
       2020-08-17 14:18:16 +08:00
    @kappa 搜索了说变量初始化后没有改变,默认就是 final,但是发现有个地方有疑问
    ```
    final String a = "hello";
    String b = a + " world";
    //编译后字节码里面会有常量替换,生成“hello world"
    ```

    ```
    String a = "hello";
    String b = a + "world";
    //按道理 a 就是 effectively final 的,但是编译后看字节码,需要在运行时上进行字符串拼接
    ```
    haosamax
        17
    haosamax  
       2020-08-17 15:44:41 +08:00
    同感,private 、final 感觉可用可不用,可惜!
    Cstone
        18
    Cstone  
       2020-08-17 17:11:30 +08:00
    Cstone
        19
    Cstone  
       2020-08-17 17:11:59 +08:00
    之前做的一个简单的 final 用法小归纳
    aguesuka
        20
    aguesuka  
       2020-08-17 19:12:33 +08:00
    @MakHoCheung https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4
    我测试过了,没有显示声明 final 使用默认参数确实不会优化,但是我觉得编译优化是编译器的工作,不应该由程序员来完成
    draymonder
        21
    draymonder  
       2020-09-01 12:16:39 +08:00
    补充一点: 不用从数据库里读出来的时候
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6052 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 02:40 · PVG 10:40 · LAX 18:40 · JFK 21:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.