关于Java中的本地最终变量

在java Program中,参数在方法声明中定义为String 。 但是在方法定义中,它作为final String变量被访问。 它是否会导致某些问题(如安全性,内存问题)?

例如:

方法声明

 join(String a,String b); 

方法定义

 public void join(final String a,final String b) { Authenticator au = new Authenticator(){ public PasswordAuthentication getPasswordAuthentication(){ return new PasswordAuthentication(a,b)} }; } 

请帮助我,澄清我的疑虑。 提前致谢

PS我正在访问a和b作为最终变量,因为我必须在内部类中使用它。

final只是意味着不能为reference / primitive变量赋一个新值。 它与const概念(Java没有)不同; 它不保证不变性。 当然,Java中的String已经足够不可变(除非讨厌的reflection攻击)。

对参数参数使用final修饰符对安全性或垃圾回收没有影响。 这样做是为了提高可读性并强制执行编码约定,即参数变量不会在方法中重复使用以存储其他值。

在遇到final修饰符时,可以确保人类读者在分配后,该变量的值不会在其范围内发生变化。 编译器会强制执行此行为,并且不会编译非法尝试将新值分配给声明为final变量的程序。

JLS 14.2.4 final变量

变量可以声明为finalfinal变量只能分配一次。 如果分配了final变量,那么编译时错误除非在分配之前明确地未分配。

然而,如上所述, final本身并不能保证被引用对象的不变性。 final StringBuilder sb声明保证sb一旦被赋值并且在其范围内,就不会引用另一个StringBuilder实例。 当然, StringBuilder本身是一个可变对象。


final和内部课程

final修饰符的另一个用途是允许内部类使用局部变量等:

JLS 8.1.3内部类和封闭实例

使用但未在内部类中声明的任何局部变量,forms方法参数或exception处理程序参数必须声明为final

这与如何使用Java编译使用这些变量的内部类有关,这个实现细节可能与讨论不太相关。 基本上,这些final变量的值在构造时被赋予内部类。 内部类实例不会看到对局部变量的后续更改(如果允许)。 为了确保正确的语义,必须将这些局部变量声明为final


final修饰符对运行时局部变量的影响

局部变量/forms方法参数的final修饰符是编译时概念,并且不存在于字节码级别(即,它与字段,类和方法的final修饰符起着非常不同的作用)。 因此,这个概念在运行时根本不存在,其中final和非final局部变量是难以区分的; 关键字本身的使用不会对垃圾收集和/或性能产生任何影响。

垃圾收集性是根据是否存在对象的实时引用来定义的。 无论它们是否被声明为final ,本地变量和方法参数都超出了方法末尾的范围(或者它们被声明的块)。 超出范围意味着参考“死”。 对象本身可能仍然有来自其他地方的实时引用。

在这种特殊情况下,forms化方法参数被声明为final以便它们可以在内部类中使用。 如上所述,内部类将复制这些引用以供自己使用。 因此,在这种特殊情况下, Authenticator对象将引用ab引用的String对象。

简单地说,对一个对象的引用越多,就越难以认定为垃圾难以收集。 然而,潜在因素是这些参考文献的活跃性,而不是它们是否是final


关于分析

理解这些概念以清除对内存使用/性能问题的任何疑问是很好的。 最好只是分析并查看问题是否真实,并根据需要进行修复。 精心设计的系统应该能够高度适应这些变化。

不,参数的final只会影响方法堆栈框架上参数的本地副本。 它不会以任何方式影响或更改作为参数传递的值。

使变量final与安全性或内存分配无关。 它对安全性或内存使用没有任何影响。

添加final不会更改签名或创建任何其他问题。 因此,可以在由接口指定的方法中使用(例如)。 它只对方法内部的代码产生影响。