浏览 android 教程(与多线程、loopers 和处理程序相关),我遇到了这个:
public synchronized void enqueueDownload(final DownloadTask task)
我的问题是:
- 何时以及为什么需要将函数的参数声明为 final?
- 它是 Java 特有的还是其他语言(如 C/C++)中存在类似的东西?
浏览 android 教程(与多线程、loopers 和处理程序相关),我遇到了这个:
public synchronized void enqueueDownload(final DownloadTask task)
我的问题是:
在 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
}
在您的上下文中,该参数上的 final 关键字意味着变量 task 不能在方法主体内重新分配,并且出于安全原因指定它。
可以在 C++ 中使用常量函数参数实现类似的行为:
如果你正在编写一个函数并且你不打算修改一个参数,你可以声明它是一个常量引用参数。
如果你知道它永远不应该被重新分配,你就声明它是最终的。您经常希望对方法参数执行此操作,因为重新分配方法参数几乎没有意义。
void foo(String str) { // no final
str = "hijacked"; // perfectly fine
}
void foo(final String str) { // final
str = "hijacked"; // compile error
}
C 和 C++ 使用const
代替final
,但我不能声称自己知道细节。
final 关键字在几种不同的上下文中用作修饰符,这意味着它修饰的内容在某种意义上不能更改。
最后的课程
您会注意到 Java 库中的一些类被声明为 final,例如
public final class String 这意味着这个类不会被子类化,并通知编译器它可以执行某些优化,否则它不能。它还在安全性和线程安全方面提供了一些好处。
编译器不会让您子类化任何声明为 final 的类。不过,您可能不希望或不需要将自己的类声明为 final。
最终方法
您还可以声明方法是最终的。声明为 final 的方法不能在子类中被覆盖。语法很简单,只需将关键字 final 放在访问说明符之后和返回类型之前,如下所示:
public final String convertCurrency()
最终字段
您也可以将字段声明为最终字段。这与将方法或类声明为 final 不同。当一个字段被声明为 final 时,它是一个不会也不能改变的常量。它可以设置一次(例如在构造对象时,但之后无法更改。)尝试更改它会生成编译时错误或异常(取决于尝试的偷偷摸摸程度)。
既是 final、static 和 public 的字段实际上是命名的常量。例如,一个物理程序可能定义 Physics.c,光速为
public class Physics {
public static final double c = 2.998E8;
}
在 SlowCar 类中,speedLimit 字段可能既是 final 也是静态的,尽管它是私有的。
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;
}
}
最后的论点
最后,您可以声明方法参数是最终的。这意味着该方法不会直接更改它们。由于所有参数都是按值传递的,因此这不是绝对必需的,但它有时会有所帮助。