将函数的参数声明为final:为什么以及何时需要它?

时间:2011-11-18 19:16:38

标签: java android final function-parameter

通过Android的教程(与多线程,loopers和处理程序相关),我遇到了这个:

public synchronized void enqueueDownload(final DownloadTask task)

我的问题是:

  1. 何时以及为什么需要将函数的参数声明为final?
  2. 它是特定于Java还是在C / C ++等其他语言中存在类似的东西?

4 个答案:

答案 0 :(得分:10)

在Java中,这通常是 ,因此您可以访问匿名内部类中的参数 - 这通常在Android中用于事件处理程序等。

真正的含义是参数的值不能在方法中更改,但目的通常用于匿名内部类......

public synchronized void enqueueDownload(final DownloadTask task) {
    SomethingHandler handler = new SomethingHandler() {
        @Override public void handleSomething() {
            // This would not compile if task were not final
            task.doSomething();
        }
    };
    // Use handler
}

答案 1 :(得分:2)

在您的上下文中,该参数的final关键字意味着无法在方法体内重新分配变量任务,并且出于安全原因而指定它。

使用常量函数参数可以在C ++中实现类似的行为:

  

如果您正在编写函数而您不打算修改   参数,您可以声明它是一个常量引用参数。

答案 2 :(得分:1)

如果您知道它永远不会被重新分配,那么您将某些内容声明为最终内容。您经常希望对方法参数执行此操作,因为重新分配方法参数很少有意义。

void foo(String str) { // no final
    str = "hijacked"; // perfectly fine
}

void foo(final String str) { // final
    str = "hijacked"; // compile error
}

C和C ++使用const代替final,但我无法声称知道具体细节。

答案 3 :(得分:1)

final关键字在几个不同的上下文中用作修饰符,意味着它修改的内容在某种意义上无法更改。

最后的课程

您会注意到Java库中的许多类都被声明为final,例如

public final class String 这意味着该类不会被子类化,并通知编译器它可以执行某些优化,否则它不能执行。它还在安全性和线程安全方面提供了一些好处。

编译器不会让你继承任何声明为final的类。您可能不希望或者需要声明自己的最终类。

最终方法

您还可以声明方法是最终的。声明为final的方法不能在子类中重写。语法很简单,只需将关键字final放在访问说明符之后和返回类型之前,如下所示:

public final String convertCurrency()

最终字段

您也可以声明字段为final。这与将方法或类声明为final是不同的。当一个字段被声明为final时,它是一个不会也不会改变的常量。它可以设置一次(例如,在构造对象时,但在此之后无法更改。)尝试更改它将生成编译时错误或异常(取决于尝试的偷偷摸摸程度)。

最终,静态和公共字段都是有效命名的常量。例如,物理程序可能会定义Physics.c,光速为

public class Physics {

  public static final double c = 2.998E8;


}

在SlowCar类中,speedLimit字段可能既是final也是static,尽管它是私有的。

public class SlowCar extends Car {

  private final static double speedLimit = 112.65408; // kph == 70 mph

  public SlowCar(String licensePlate, double speed, double maxSpeed,
   String make, String model, int year, int numberOfPassengers, int numDoors) {
    super(licensePlate, 
     (speed < speedLimit) ? speed : speedLimit, 
     maxSpeed, make, model, year, numberOfPassengers, numDoors);
  }

  public void accelerate(double deltaV) {

     double speed = this.speed + deltaV;

     if (speed > this.maxSpeed) {
       speed = this.maxSpeed; 
     }

     if (speed > speedLimit) {
       speed = speedLimit;
     }

     if (speed < 0.0) {
       speed = 0.0; 
     } 

     this.speed = speed;    

  }

}

最终论点

最后,您可以声明方法参数是final。这意味着该方法不会直接更改它们。由于所有参数都是按值传递的,因此这不是绝对必需的,但它偶尔会有所帮助。