注意:final 修饰的变量不能被赋值这种说法是错误的,严格的说法是,final 修饰的变量不可被改变,一旦获得了初始值,该 final 变量的值就不能被重新赋值。
public class FinalDemo { void doSomething() { // 没有在声明的同时赋值 final int e; // 只能赋值一次 e = 100; System.out.print(e); // 声明的同时赋值 final int f = 200; } // 实例常量 final int a = 5; // 直接赋值 final int b; // 空白final变量 // 静态常量 final static int c = 12;// 直接赋值 final static int d; // 空白final变量 // 静态代码块 static { // 初始化静态变量 d = 32; } // 构造方法 FinalDemo() { // 初始化实例变量 b = 3; // 第二次赋值,会发生编译错误 // b = 4; } }上述代码第 4 行和第 6 行是声明局部常量,其中第 4 行只是声明没有赋值,但必须在使用之前赋值(见代码第 6 行),其实局部常量最好在声明的同时初始化。代码第 13、14、16 和 17 行都声明成员常量。代码第 13 和 14 行是实例常量,如果是空白 final 变量(见代码第 14 行),则需要在构造方法中初始化(见代码第 27 行)。代码第 16 和 17 行是静态常量,如果是空白 final 变量(见代码第 17 行),则需要在静态代码块中初始化(见代码第 21 行)。
import java.util.Arrays; class Person { private int age; public Person() { } // 有参数的构造器 public Person(int age) { this.age = age; } // 省略age的setter和getter方法 // age 的 setter 和 getter 方法 } public class FinalReferenceTest { public static void main(String[] args) { // final修饰数组变量,iArr是一个引用变量 final int[] iArr = { 5, 6, 12, 9 }; System.out.println(Arrays.toString(iArr)); // 对数组元素进行排序,合法 Arrays.sort(iArr); System.out.println(Arrays.toString(iArr)); // 对数组元素赋值,合法 iArr[2] = -8; System.out.println(Arrays.toString(iArr)); // 下面语句对iArr重新赋值,非法 // iArr = null; // final修饰Person变量,p是一个引用变量 final Person p = new Person(45); // 改变Person对象的age实例变量,合法 p.setAge(23); System.out.println(p.getAge()); // 下面语句对P重新赋值,非法 // p = null; } }从上面程序中可以看出,使用 final 修饰的引用类型变量不能被重新赋值,但可以改变引用类型变量所引用对象的内容。例如上面 iArr 变量所引用的数组对象,final 修饰后的 iArr 变量不能被重新赋值,但 iArr 所引用数组的数组元素可以被改变。与此类似的是,p 变量也使用了 final 修饰,表明 p 变量不能被重新赋值,但 p 变量所引用 Person 对象的成员变量的值可以被改变。
public static final String SEX= "女";
public class FinalMethodTest { public final void test() { } } class Sub extends FinalMethodTest { // 下面方法定义将出现编译错误,不能重写final方法 public void test() { } }上面程序中父类是 FinalMethodTest,该类里定义的 test() 方法是一个 final 方法,如果其子类试图重写该方法,将会引发编译错误。
public class PrivateFinalMethodTest { private final void test() { } } class Sub extends PrivateFinalMethodTest { // 下面的方法定义不会出现问题 public void test() { } }上面程序没有任何问题,虽然子类和父类同样包含了同名的 void test() 方法,但子类并不是重写父类的方法,因此即使父类的 void test() 方法使用了 final 修饰,子类中依然可以定义 void test() 方法。
public class FinalOverload { // final 修饰的方法只是不能被重写,完全可以被重载 public final void test(){} public final void test(String arg){} }
final class SuperClass { } class SubClass extends SuperClass { //编译错误 }因为 SuperClass 类是一个 final 类,而 SubClass 试图继承 SuperClass 类,这将会引起编译错误。
本文链接:http://task.lmcjl.com/news/10522.html