方法参数中的final关键字

发布于 2024-08-20 18:01:26 字数 185 浏览 6 评论 0原文

我经常遇到如下所示的方法:

public void foo(final String a, final int[] b, final Object1 c){
}

如果调用此方法而不传递最终参数,会发生什么情况。即稍后更改的 Object1(因此未声明为 Final)可以传递给此方法就好了

I often encounter methods which look like the following:

public void foo(final String a, final int[] b, final Object1 c){
}

What happens if this method is called without passing it final parameters. i.e. an Object1 that is later changed (so is not declared as final) can be passed to this method just fine

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(9

流绪微梦 2024-08-27 18:01:26

Java 在将参数发送到方法之前总是会复制参数。这意味着最终的结果对于调用代码来说没有任何区别。这仅意味着在方法内部不能重新分配变量。

请注意,如果您有最终对象,您仍然可以更改该对象的属性。这是因为 Java 中的对象实际上是指向对象的指针。并且仅复制指针(并且在您的方法中将是最终的),而不是实际的对象。

Java always makes a copy of parameters before sending them to methods. This means the final doesn't mean any difference for the calling code. This only means that inside the method the variables can not be reassigned.

Note that if you have a final object, you can still change the attributes of the object. This is because objects in Java really are pointers to objects. And only the pointer is copied (and will be final in your method), not the actual object.

烟花肆意 2024-08-27 18:01:26

在某些情况下,您需要将其声明为final,否则会导致编译错误,即将它们传递到匿名类或lambda。这是使用匿名类的基本示例:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = new FileFilter() {
        public boolean accept(File file) {
            return file.getName().endsWith(extension);
        }
    };

    // Imagine what would happen when we're allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

这是 lambda 风格的完全相同的示例:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = file -> file.getName().endsWith(extension);

    // Imagine what would happen when we're allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

删除 final 修饰符将导致编译错误,因为不再保证该值是运行时常量。在创建匿名类或 lambda 后更改值将导致匿名类或 lambda 的实例在创建后表现不同。

There is a circumstance where you're required to declare it final —otherwise it will result in compile error—, namely passing them through into an anonymous class or a lambda. Here's a basic example using an anonymous class:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = new FileFilter() {
        public boolean accept(File file) {
            return file.getName().endsWith(extension);
        }
    };

    // Imagine what would happen when we're allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

And here's the exact same example in lambda flavor:

public FileFilter createFileExtensionFilter(final String extension) {
    FileFilter fileFilter = file -> file.getName().endsWith(extension);

    // Imagine what would happen when we're allowed to change extension here?
    // extension = "foo";

    return fileFilter;
}

Removing the final modifier would result in compile error, because it isn't guaranteed anymore that the value is a runtime constant. Changing the value after creation of the anonymous class or lambda would namely cause the instance of the anonymous class or lambda to behave different after the moment of creation.

空城仅有旧梦在 2024-08-27 18:01:26

Java只是按值传递。 (或者更好 - 按值传递引用)

因此,传递的参数和方法内的参数是指向同一对象(值)的两个不同的处理程序。

因此,如果您更改对象的状态,它会反映到引用它的所有其他变量。但是,如果您将新对象(值)重新分配给参数,则指向该对象(值)的其他变量不会被重新分配。

Java is only pass-by-value. (or better - pass-reference-by-value)

So the passed argument and the argument within the method are two different handlers pointing to the same object (value).

Therefore if you change the state of the object, it is reflected to every other variable that's referencing it. But if you re-assign a new object (value) to the argument, then other variables pointing to this object (value) do not get re-assigned.

风追烟花雨 2024-08-27 18:01:26

方法参数上的final 关键字对调用者来说绝对没有任何意义。它对于正在运行的程序也绝对没有任何意义,因为它的存在或不存在不会改变字节码。它仅确保如果在方法内重新分配参数变量,编译器会发出警告。就这样。但这就足够了。

一些程序员(比如我)认为这是一件非常好的事情,并且在几乎每个参数上都使用 final 。它使理解长或复杂的方法变得更容易(尽管有人可能会认为应该重构长且复杂的方法。)它还突出了标记有 的方法参数。最终

The final keyword on a method parameter means absolutely nothing to the caller. It also means absolutely nothing to the running program, since its presence or absence doesn't change the bytecode. It only ensures that the compiler will complain if the parameter variable is reassigned within the method. That's all. But that's enough.

Some programmers (like me) think that's a very good thing and use final on almost every parameter. It makes it easier to understand a long or complex method (though one could argue that long and complex methods should be refactored.) It also shines a spotlight on method parameters that aren't marked with final.

自我难过 2024-08-27 18:01:26

考虑 foo() 的实现:

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}

因为 Runnable 实例的寿命会比该方法长,因此如果没有 final 关键字,则无法编译 - final告诉编译器可以安全地获取引用的副本(以便稍后引用)。因此,参考被认为是最终的,而不是。换句话说:作为呼叫者,你不能搞砸任何事情......

Consider this implementation of foo():

public void foo(final String a) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            System.out.print(a);
        }
    }); 
}

Because the Runnable instance would outlive the method, this wouldn't compile without the final keyword -- final tells the compiler that it's safe to take a copy of the reference (to refer to it later). Thus, it's the reference that's considered final, not the value. In other words: As a caller, you can't mess anything up...

不气馁 2024-08-27 18:01:26

final 意味着一旦分配该变量的值就无法更改。

同时,在这些方法中使用final作为参数意味着不允许程序员在方法执行期间更改它们的值
这仅意味着在方法内部,final 变量无法重新分配。

final means you can't change the value of that variable once it was assigned.

Meanwhile, the use of final for the arguments in those methods means it won't allow the programmer to change their value during the execution of the method.
This only means that inside the method the final variables can not be reassigned.

青春有你 2024-08-27 18:01:26

如果将任何参数声明为final,则无法更改其值。

class Bike11 {  
    int cube(final int n) {  
        n=n+2;//can't be changed as n is final  
        n*n*n;  
     }  
    public static void main(String args[]) {  
        Bike11 b=new Bike11();  
        b.cube(5);  
    }  
}   

输出:编译时错误

有关更多详细信息,请访问我的博客:http://javabyroopam.blogspot.com

If you declare any parameter as final, you cannot change the value of it.

class Bike11 {  
    int cube(final int n) {  
        n=n+2;//can't be changed as n is final  
        n*n*n;  
     }  
    public static void main(String args[]) {  
        Bike11 b=new Bike11();  
        b.cube(5);  
    }  
}   

Output: Compile Time Error

For more details, please visit my blog: http://javabyroopam.blogspot.com

怀念你的温柔 2024-08-27 18:01:26

方法输入参数中不需要final关键字。 Java创建了对象引用的副本,因此将final放在上面并不会使对象成为final,而只是引用,这是没有意义的

final keyword in the method input parameter is not needed. Java creates a copy of the reference to the object, so putting final on it doesn't make the object final but just the reference, which doesn't make sense

谈下烟灰 2024-08-27 18:01:26

字符串是不可变的,因此实际上您不能在之后更改字符串(只能使保存字符串对象的变量指向不同的字符串对象)。

但是,这并不是您可以将任何变量绑定到 final 参数的原因。所有编译器都会检查参数是否在方法内重新分配。这对于文档目的很有用,可以说是良好的风格,甚至可以帮助优化字节代码以提高速度(尽管这在实践中似乎没有多大作用)。

但即使您确实在方法中重新分配了参数,调用者也不会注意到这一点,因为 java 的所有参数都是按值传递的。在序列之后,

  a = someObject();
  process(a);

a 的字段可能已更改,但 a 仍然是之前的同一对象。在引用传递语言中,这可能不是真的。

Strings are immutable, so actully you can't change the String afterwards (you can only make the variable that held the String object point to a different String object).

However, that is not the reason why you can bind any variable to a final parameter. All the compiler checks is that the parameter is not reassigned within the method. This is good for documentation purposes, arguably good style, and may even help optimize the byte code for speed (although this seems not to do very much in practice).

But even if you do reassign a parameter within a method, the caller doesn't notice that, because java does all parameter passing by value. After the sequence

  a = someObject();
  process(a);

the fields of a may have changed, but a is still the same object it was before. In pass-by-reference languages this may not be true.

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