final可以修饰变量:被final修饰的变量被赋初值之后,不能对它重新复制。
final可以修饰方法,被final修饰的方法不能被重写。
final可以修饰类,被final修饰的类不能派生子类。
被final修饰的变量必须显式指定初始值,而且只能在如下3个位置指定初始值:
1),定义final实例变量的时候指定;
2),在非静态初始化块中为final实例变量指定初始值;
3),在构造器中为final实例变量指定初始值。
public class FinalInstanceTest { final int var1 ="crazy Java".length(); final int var2; final int var3; { var2 ="abcesdgd".length(); } public FinalInstanceTest() { this.var3 = "xxxxxy".length(); } public static void main(String[] args) { FinalInstanceTest fiv = new FinalInstanceTest(); System.out.println(fiv.var1); System.out.println(fiv.var2); System.out.println(fiv.var3); } }
被final修饰的类变量只能在两个地方指定初始值:
1),定义final类变量时指定;
2),在静态初始化块中为final类变量进行初始化;
final static int var4 = 90;
final static int var5;
static
{
var5 = 1000;
}
内部类中的局部变量:
如果程序需要在匿名内部类中使用局部变量,这个局部变量必须使用final修饰。
Java要求被内部类访问的局部变量都使用final修饰的原因:对于普通局部变量而言,它的作用域就是停留在该方法内,当方法执行结束,该局部变量也随之消失;但内部类则可能产生隐式的“闭包Closure”,闭包将使得局部变量脱离它所在的方法继续存在。
1 import java.util.Arrays; 2 3 public class FinalCommandTest { 4 5 public int [] process (IntArrayProductor cmd, int length) 6 { 7 int [] result = new int[length]; 8 for(int i=0;i<length;i++) 9 { 10 result[i] = cmd.product(); 11 } 12 return result; 13 } 14 public static void main(String[] args) 15 { 16 FinalCommandTest ct = new FinalCommandTest(); 17 final int seed =5; 18 int [] result = ct.process(new IntArrayProductor() { 19 20 @Override 21 public int product() { 22 // TODO Auto-generated method stub 23 return (int) Math.round(Math.random()*seed); 24 } 25 }, 6); 26 System.out.println(Arrays.toString(result)); 27 } 28 29 } 30 31 interface IntArrayProductor 32 { 33 int product(); 34 }
局部变量脱离它所在方法继续存在的例子:
1 public class ClosureTest { 2 3 public static void main(String[] args) 4 { 5 final String str ="Java"; 6 new Thread(new Runnable() 7 { 8 public void run() 9 { 10 for(int i=0;i<100;i++) 11 { 12 System.out.println(str+" "+i); 13 try 14 { 15 Thread.sleep(100); 16 } 17 catch (Exception e) 18 { 19 e.printStackTrace(); 20 } 21 } 22 } 23 }).start(); 24 } 25 }
在main方法中定义的str 对象,main方法的生命周期介绍之后,局部变量str的作用域也会随之结束,但只要新线程里的run方法没有执行完,匿名内部类的实例的生命周期就没有结束,将一直可以访问str局部变量的值。这就是内部类会扩大局部变量作用域的例子。