源码阅读之final

final这个关键字, 其实在多种语言中都有出现, 对普通人而言, 我们使用它的频率肯定是不多的, 常见场景就是把它当C/C++中的 const 来定义常量, 那么通过阅读不少源码后, 会发现它的出场频率极其的高,有必要全面的认真学习一下它.

PS:关于源码中函数式编程的内容参考之前一篇 ,后续衍变为源码阅读系列 ?

0x00.简介

简单的定义:

final的作用是–使其修饰的变量是不可改变的, 使用它目的是改善设计效率, 也就是说当你看到使用final的地方, 不知道为什么用, 就从这两个方面去想, 效率简单可以理解为C/C++中的宏和常量.

其实final在不同的场景下, 语义是相差甚多的,想深入理解final, 必须全面的对它探究一番

final可以修饰OOP中大部分元素. 大体分为4类:

  • Variable/Field (变量/域)
  • Method (方法)
  • Class (类)
  • Method params (方法的形参,特别)

final修饰时位于static后, 类型前, 比如public static final float num = 0.1f; 用于修饰变量的时候是最好理解的, 效果类似于const(常量) ,但是补充说一句,其实const在java中也是作为一个保留字 存在的,只不过基本不会使用. 那么大家关注的核心显然是再后面修饰方法和修饰类上 .

0x01.从表面看final

表面看它其实很容易被滥用, 因为大部分人写代码不会考虑很好的向下兼容和后续重写, 所以工程上说, 除了跟宏一样过度使用会导致打破平衡点, 我觉得还是推荐默认使用的.

也就是说, 如果你不知道这个类/方法/对象是否需要改变/继承/重写, 可以都当默认成不需要 **, 这也是为什么源码里面的确会超大量**的使用final, 并不是说那个地方非得final ,而是形成了习惯, 就像C/C++中宏也会被滥用, 但是各种库,甚至内核里照样到处都是…

0x02.从编译器看final

有点懒得写… 因为内联其实很像宏, 宏我觉得挺好理解了, 再从JVM角度去磕意义不大, 有兴趣的可以自己反编译看看字节码.

0x03.综合来看final

先来个简单总结吧, 其实看完final发现其实不管是从什么角度, 编译器, 类加载器或者是设计模式上, 都是很难简单说清楚它的精准用法的. 效率起见, 先说一下大部分时候它四个修饰场景的意义:

  • 修饰class 的时候, 此时这个类不能被任何类继承. 默认class中所有方法也都是final的, 所有方法类似于C中的化, 大部分时候调用效率会提高.
  • 单独修饰方法. 除了避免被重写(实际也很少见), 也就是宏化提高效率
  • 修饰基本类型基本等同于常量, 编译器可以更快读取. 修饰对象类型, 本质使其引用固定? 意义?
  • 修饰形参(方法中的), 用处? (这个说实话我还没很认真看hh, 后续补一下)

以后接着补完,先看其他源码去了…

有时候发现坚持写blog的确不容易….因为种种原因,现在每次都得多PC倒腾md, 很多时候不是习惯了,还真的可能跟其他人一样,就随便看看或者丢有道之类的懒得发了. 不过还是坚持下来吧~~