Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。


用 final 声明的局部变量,能提升性能吗

在面试交流群中,有个群友问了我一个问题,这个问题也欢迎大家一起留言讨论,

Q:声明为 final 类型的局部变量,可以提升性能吗?

在 Java 中,声明为 final 的局部变量通常不会直接带来显著的性能提升。无论局部变量声明时带不带 final 关键字修饰,对其访问的效率都一样。

// 不带final
int fun1() {
  int a = someValueA();
  int b = someValueB();
  return a + b; // 这里访问局部变量
}

// 带final
int fun2() {
  final int a = someValueA();
  final int b = someValueB();
  return a + b; // 这里访问局部变量
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

编译后的字节吗。

用final声明的局部变量,能提升性能吗_局部变量

从图中可以看出带不带 final 的局部变量编译后的 Class 文件都是一样的,因此访问效率都是一样的。但有一个例外,声明为 final 的局部常量。

int fun1() {
  final int a = 2; // 声明常量a
  final int b = 3; // 声明常量b
  return a + b;    // 常量表达式
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

在编译为常量时,会进行常量折叠,编译得到对应的字节码。

用final声明的局部变量,能提升性能吗_局部变量_02

实际的效果和下面的代码类似。

int fun1() {
  return 5;
}
  • 1.
  • 2.
  • 3.

那么用 final 声明的局部变量有什么作用吗?其实主要用于解决在匿名内部类中使用的外部局部变量时,该局部变量只能是用 final 声明的变量,主要有以下几个原因:

生命周期的不一致性

因为当方法执行结束时,方法内的参数和局部变量会跟着方法一起结束,都会被回收,而内部类的生命周期可能比方法长(例如:线程)。

如果允许修改外部局部变量,而外部方法已经结束,变量可能已经被回收,这会导致数据不一致和不可预测的结果。

通过将变量声明为 final,可以确保在匿名内部类中使用的变量值在其创建时就被固定下来,不会在后续发生变化。

数据一致性和线程安全

  • 由于匿名内部类可能会在不同的线程中被执行,如果允许修改外部局部变量,可能会引发线程安全问题。使用 final 变量可以保证在多个线程中看到的变量值是一致的。
  • 匿名内部类会复制外部局部变量的值。为了保证这个复制的值不会因为外部变量的修改而变得不一致,就要求外部变量是 final 的。

Hi 大家好,我是 DHL,大厂程序员,公众号:ByteCode ,在美团、快手、小米工作过。搞过逆向,做过性能优化,研究过系统,擅长鸿蒙、Android、Kotlin、性能优化、职场分享。