以关键字final修饰的最终变量,该变量一旦赋值就不得修改其值。
1.基础
例如
final int i=2;// final变量,其值不可更改
final Mother myMother=new Mother(); // final变量myMother,其值不能更改
当final变量是基本类型,它保存的值不能改变;当final变量是引用类型,它保存的值即引用值仍然不得改变,myMother指向自己的母亲,母亲总是那个母亲,但是母亲对象自己的数据却可以变化,如歌中唱到“一年一年风霜遮盖了笑脸”。
2.final修饰形参
大多数情况下,final修饰形参没有意义,因为,按照按值传递,给形参赋值通常是没有意义的。
static void test1(/*final*/ String s){
System.out.println(s);
s = "hi";//有病
System.out.println(s);
}
当然,如果形参的值在方法体中的变化有意义除外,例如:
static void test2(int i){
int[] arr = {0,1,2,3,4,5};
for(;i<arr.length;i++){//有意义
System.out.println(arr[i]);
}
}
在Java 8之前,
局部类和匿名类只能访问外包方法的final局部变量,现在只能够访问
实际上的final变量。
也就是说,下面代码中x,y前的final可以省略,但是yqj2065觉得还是不省略为好。【参考 9.4.4-9.4.5】
public Ix go(/*final*/ int x){//Ix接口有foo()
/*final*/ int y=0;
//y++;//还是不省略的好
return new Ix(){
@Override public void foo(){
// x++;//实际上的final变量
System.out.println("x + y ="+x+y);
}
}
}
3.实际上的final变量
go()方法可以用下面的代码简化
public Ix go( int x){
/*final*/ int y=0;
return ()->System.out.println("x + y ="+x+y);
}
public void m(Ix x){
x.foo();
}
lambda表达式需要使用实际上的final变量。下面的代码编译有问题,循环变量i
for(int i =5;i>0;i--){
/*final*/ int j =i;
a.m(()->System.out.println("hi"+i));//a是可以调用m()的对象,如果上面的代码放在Test类中,a = Test()
}
把lambda表达式中的i 改成 j即可。
()->System.out.println("hi"+j)