关于Java中的局部final变量
在java程序中,参数在方法声明中定义为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)}
};
}
请帮助我并澄清我的疑问。预先
感谢我将 a 和 b 作为最终变量访问,因为我必须在内部类中使用它。
In java Program, parameters which is defined as String
in method declaration. But in method definition it is accessed as final String
variable. Whether it'll lead to some issues (like security, memory problem)?
For Example:
Method Declaration
join(String a,String b);
Method definition
public void join(final String a,final String b)
{
Authenticator au = new Authenticator(){
public PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication(a,b)}
};
}
Please help for me and clarify my doubts. Thanks in advance
P.S. I'm accessing a and b as final variable because I've got to use it in the inner class.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
final
只是意味着不能为引用/原始变量分配新值。它与const
概念不同(Java没有);它不保证不变性。当然,Java 中的String
已经足够不可变了(除非讨厌的反射攻击)。对参数参数使用
final
修饰符不会对安全性或垃圾回收产生影响。这样做是为了提高可读性并强制执行编码约定,即参数变量不会在方法中重用来存储其他值。在遇到
final
修饰符时,人类读者可以放心,该变量的值一旦分配,就不会在其范围内改变。编译器将强制执行此行为,并且不会编译非法尝试为声明为final
的变量分配新值的程序。然而,如前所述,
final
本身并不保证所引用对象的不变性。final StringBuilder sb
声明保证sb
一旦被分配并在其范围内,就不会引用另一个StringBuilder
实例。当然,StringBuilder
本身是一个可变对象。final
和内部类final
修饰符的另一个用途是允许内部类使用局部变量等:这与使用这些变量的内部类在 Java 中的编译方式有关,这个实现细节可能与讨论不太相关。本质上,这些
final
变量的值在构造时被赋予内部类。内部类实例将看不到对局部变量的后续更改(如果允许)。为了确保正确的语义,这些局部变量必须被声明为final
。运行时局部变量的
final
修饰符对局部变量/形式方法参数的
final
修饰符的影响是一个编译时概念,并且不存在于例如字节码级别(即它与字段、类和方法的final
修饰符扮演着非常不同的角色)。因此,这个概念在运行时根本不存在,其中final
和非final
局部变量是无法区分的;关键字本身的使用不会对垃圾回收性和/或性能产生任何影响。垃圾可收集性是根据是否存在对对象的实时引用来定义的。局部变量和方法参数在方法末尾(或声明它们的块)超出范围,无论它们是否声明为
final
。超出范围意味着引用“已死”。对象本身可能仍然具有来自其他地方的实时引用。在这种特殊情况下,形式方法参数被声明为
final
,以便它们可以在内部类中使用。如上所述,内部类将复制这些引用以供自己使用。因此,在这种特殊情况下,Authenticator
对象将引用a
和b
引用的String
对象>。简单地说,对对象的引用越多,就越难将其认定为难以收集的垃圾。然而,根本因素是这些引用的活跃度,而不是它们是否
最终
。关于分析
理解这些概念有助于消除对内存使用/性能问题的任何疑问;最好只进行分析并查看问题是否真实,并根据需要进行修复。一个设计良好的系统应该能够高度适应这些变化。
final
simply means that the reference/primitive variable can not be assigned a new value. It's not the same asconst
concept (which Java doesn't have); it does NOT guarantee immutability.String
in Java, of course, is already immutable enough (barring nasty reflection attacks).Using
final
modifier for parameter arguments will have no effect on security or garbage collection. It's done for readability and to enforce coding convention that parameter variables aren't being reused in the method to store other values.Upon encountering a
final
modifier, a human reader can be assured that the value of this variable, once assigned, will not change within its scope. The compiler would enforce this behavior, and would not compile a program that illegally tries to assign a new value to variable that is declaredfinal
.As mentioned, however,
final
does not in itself guarantee immutability of the object being referred to. Afinal StringBuilder sb
declaration guarantees thatsb
, once assigned and within its scope, will not refer to anotherStringBuilder
instance.StringBuilder
itself, of course, is a mutable object.final
and inner classesAnother use of
final
modifier is to allow local variables etc to be used by an inner class:This has to do with how inner classes using these variables are compiled in Java, an implementation detail that perhaps is not all too relevant for the discussion. Essentially, the values of these
final
variables are given to the inner classes at construction time. Subsequent changes to the local variables (if allowed) would not be seen by the inner class instance. To ensure proper semantics, these local variables must thus be declaredfinal
.Effects of
final
modifier for local variables at run-timefinal
modifier for local variables/formal method parameters is a compile-time concept, and is not present at, say, the bytecode level (i.e. it plays a very different role thanfinal
modifier for fields, classes and methods). Thus, this concept simply doesn't exist at run-time, wherefinal
and non-final
local variables are indistinguishable; the usage of the keyword itself would not have any effect on garbage collectibility and/or performance.Garbage collectibility is defined in terms of whether or not there are live references to an object. Local variables and method arguments go out of scope at the end of the method (or the block they're declared in), regardless of whether or not they're declared
final
. Going out of scope means the reference is "dead". The object itself may still have live references from elsewhere.In this particular case, the formal method parameters are declared
final
so that they can be used in an inner class. As mentioned above, the inner class would copy these references for its own use. Thus, in this particular case, theAuthenticator
object would have references to theString
objects referred to bya
andb
.Simplistically speaking, the more references to an object there are, the harder it would be to qualify as garbage illegible for collection. The underlying factor, however, is the liveness of these references, not whether or not they're
final
.On profiling
It's good to understand the concepts to clear any doubts on memory usage/performance issues; it's better to just profile and see if the issues are real, and fix them as necessary. A well-designed system should be highly adaptable to these kinds of changes.
不,参数上的
final
仅影响方法堆栈帧上参数的本地副本。它不会以任何方式影响或改变作为参数传递的值。No, the
final
on an argument only influences the local copy of the argument on the stack frame of the method. It does not in any way influence or change the value passed as an argument.将变量设为
final
与安全性或内存分配没有任何关系。它对安全性或内存使用没有任何影响。Making the variables
final
does not have anything to do with security or memory allocation. It does not have any impact on security or memory use.添加
final
不会更改签名或产生任何其他问题。因此,可以在接口(例如)指定的方法中使用。它只对方法内部的代码产生影响。Adding
final
doesn't change the signature or create any other issues. Thus, it is fine to use in a method specified by an interface (for instance). It only makes a difference to code inside the method.