关于Java中的局部final变量

发布于 2024-09-05 01:55:13 字数 547 浏览 3 评论 0原文

在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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

独享拥抱 2024-09-12 01:55:14

final 只是意味着不能为引用/原始变量分配新值。它与const概念不同(Java没有);它保证不变性。当然,Java 中的 String 已经足够不可变了(除非讨厌的反射攻击)。

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

在遇到 final 修饰符时,人类读者可以放心,该变量的值一旦分配,就不会在其范围内改变。编译器将强制执行此行为,并且不会编译非法尝试为声明为 final 的变量分配新值的程序。

JLS 14.2.4 final 变量

变量可以声明为finalfinal 变量只能分配一次。如果分配了 final 变量,则会出现编译时错误,除非在分配之前立即明确未分配该变量。

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


final 和内部类

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

JLS 8.1.3 内部类和封装实例

任何使用但未在内部类中声明的局部变量、形式方法参数或异常处理程序参数都必须声明为 final

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


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

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

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

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

简单地说,对对象的引用越多,就越难将其认定为难以收集的垃圾。然而,根本因素是这些引用的活跃度,而不是它们是否最终


关于分析

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

final simply means that the reference/primitive variable can not be assigned a new value. It's not the same as const 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 declared final.

JLS 14.2.4 final Variables

A variable can be declared final. A final variable may only be assigned to once. It is a compile time error if a final variable is assigned to unless it is definitely unassigned immediately prior to the assignment.

As mentioned, however, final does not in itself guarantee immutability of the object being referred to. A final StringBuilder sb declaration guarantees that sb, once assigned and within its scope, will not refer to another StringBuilder instance. StringBuilder itself, of course, is a mutable object.


final and inner classes

Another use of final modifier is to allow local variables etc to be used by an inner class:

JLS 8.1.3 Inner Classes and Enclosing Instances

Any local variable, formal method parameter or exception handler parameter used but not declared in an inner class must be declared final.

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 declared final.


Effects of final modifier for local variables at run-time

final 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 than final modifier for fields, classes and methods). Thus, this concept simply doesn't exist at run-time, where final 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, the Authenticator object would have references to the String objects referred to by a and b.

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.

烟雨凡馨 2024-09-12 01:55:14

不,参数上的 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.

不…忘初心 2024-09-12 01:55:14

将变量设为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.

半步萧音过轻尘 2024-09-12 01:55:14

添加 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文