在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)}
};
}
请帮助我并澄清我的疑虑。提前致谢
P.S。我正在访问a和b作为最终变量,因为我必须在内部类中使用它。
答案 0 :(得分:18)
final
仅表示无法为引用/原始变量分配新值。它与const
概念(Java没有)概念不同;它 NOT 保证不变性。当然,Java中的String
已经足够不可变(除非讨厌的反射攻击)。
对参数参数使用final
修饰符对安全性或垃圾回收没有影响。这样做是为了提高可读性并强制执行编码约定,即参数变量不会在方法中重复使用以存储其他值。
遇到final
修饰符后,可以确保人类读者在分配后,该变量的值不会在其范围内发生变化。编译器会强制执行此行为,并且不会编译非法尝试将新值分配给声明为final
的变量的程序。
JLS 14.2.4
final
Variables变量可以声明为
final
。final
变量只能分配一次。如果分配了final
变量,那么编译时错误除非在分配之前明确地未分配。
如上所述,final
本身并不能保证被引用对象的不变性。 final StringBuilder sb
声明保证sb
一旦被分配并且在其范围内,将不会引用另一个StringBuilder
实例。当然,StringBuilder
本身就是一个可变对象。
final
和内部类 final
修饰符的另一个用途是允许内部类使用局部变量等:
JLS 8.1.3 Inner Classes and Enclosing Instances
使用但未在内部类中声明的任何局部变量,形式方法参数或异常处理程序参数必须声明为
final
。
这与如何使用Java编译使用这些变量的内部类有关,这个实现细节可能与讨论不太相关。本质上,这些final
变量的值在构造时被赋予内部类。内部类实例不会看到对局部变量的后续更改(如果允许)。为了确保正确的语义,必须将这些局部变量声明为final
。
final
修饰符对运行时局部变量的影响 final
修饰符是编译时概念,并且不存在于字节码级别(即它与final
修饰符的作用非常不同。领域,类和方法)。因此,这个概念在运行时根本不存在,其中final
和非final
局部变量无法区分;关键字本身的使用不会对垃圾收集和/或性能产生任何影响。
垃圾收集性是根据是否存在对象的实时引用来定义的。无论是否声明它们final
,局部变量和方法参数都超出了方法末尾的范围(或它们声明的块)。超出范围意味着参考“死”。对象本身可能仍然有来自其他地方的实时引用。
在这种特殊情况下,形式化方法参数被声明为final
,以便它们可以在内部类中使用。如上所述,内部类将复制这些引用以供自己使用。因此,在这种特殊情况下,Authenticator
对象将引用String
和a
引用的b
个对象。
简单地说,对一个对象的引用越多,就越难以成为垃圾难以收集的垃圾。然而,潜在因素是这些参考文献的活跃度,而不是它们是否为final
。
理解这些概念以清除对内存使用/性能问题的疑虑是很好的;最好只是分析并查看问题是否真实,并根据需要进行修复。精心设计的系统应该能够很好地适应这些变化。
答案 1 :(得分:3)
不,参数上的final
仅影响方法堆栈帧上参数的本地副本。它不会以任何方式影响或改变作为参数传递的值。
答案 2 :(得分:0)
添加final
不会更改签名或创建任何其他问题。因此,可以在接口(例如)指定的方法中使用。它只对方法内部的代码产生影响。
答案 3 :(得分:0)
使变量final
与安全性或内存分配无关。它对安全性或内存使用没有任何影响。