final关键字
1、final:修饰基础数据成员,相当于const;
1 final int i = 0;
2 i = 1;
编译器会报错:
The final local variable i cannot be assigned. It must be blank and not using a compound assignment
也就是说,final修饰基本数据类型时,一旦被赋值,就不能被修改,其实也就是只能被初始化一次,所以,这样也是合法的:
1 final int i;
2 i = 1;
3 System.out.println(i);
输出结果为1。
2、修饰类或对象引用,在java中,无法将对象声明为final,所以只能将对象的引用声明为引用, 即该引用不能再次更改指向其他对象,而该对象的内容是可以改变的。
1 final StringBuilder sb = new StringBuilder("hello");
2 // sb = new StringBuilder("world"); // compile error
3 sb.append("world");
3、修饰方法的final,表示该方法不能被子类重新定义;
4、修饰类的final,表示该类绝后。
final成员变量的初始化并不是只有定义处和构造函数中,实际上,任何可以在任何能被初始化的地方初始化(注意是初始化而不是赋值),比如初始化代码中:
1 package com.lyj.final1; 2 3 public class TestFinal { 4 5 int i; 6 final int j; 7 static final int k; 8 static TestFinal obj; 9 10 // 11 { 12 j = 1; 13 } 14 15 static { 16 k = 1; 17 } 18 19 public void test() { 20 j = 1; // compile error 21 } 22 23 public TestFinal() { 24 /* i = 1; 25 j = 2;*/ 26 } 27 28 }
final修饰方法的形参时,在java中,这种用法并不是为了防止无意的修改而影响到调用方法外的变量,不管是方法外该变量的引用还是该变量的值。如果说是防止改变方法外变量的引用,看以下代码:
1 public static void main(String[] args) { 2 3 // TODO Auto-generated method stub 4 int[] out = new int[] { 4, 5, 6 }; 5 test(out); 6 System.out.println(out[0]); 7 System.out.println(out[1]); 8 System.out.println(out[2]); 9 } 10 11 public static void test(int[] x) { 12 x = new int[] { 1, 2, 3 }; 13 }
这段代码中test方法的形参x,如果加上final:
1 public static void test( final int[] x) { 2 int[] y = x; 3 y = new int[] { 1, 2, 3 }; 4 }
只是需要我们自己再增加声明一个变量int[] y而已,java自身在传递形参时,复制了一份实参的值(即指向对象的引用),所以在函数内部修改的只是实参的拷贝,这与用不用final修饰没有半毛钱关系,程序输出还是4,5,6。
如果说是为了防止改变变量引用所指向的值,就更不靠谱了,java中的final从来就只能保证引用不被修改,而不是值。