Java关键字介绍之final

在Java中声明属性、方法和类时,可使用关键字final来修饰。final变量即为常量,只能 赋值一次;final方法不能被子类重写;final类不能被继承。

1.final成员

声明 final 字段有助于优化器作出更好的优化决定,因为如果编译器知道字段的值不会 更改,那么它能安全地在寄存器中高速缓存该值。final 字段还通过让编译器强制该字段为 只读来提供额外的安全级别。

1.1关于final成员赋值

1)在java中,普通变量可默认初始化。但是final类型的变量必须显式地初始化。

2)final 成员能且只能被初始化一次。

3)final成员必须在声明时(在final变量定义时直接给其赋值)或者在构造函数中被初 始化,而不能在其它的地方被初始化。

示例1 Bat.java

public class Bat {   final double PI = 3.14; // 在定义时赋值   final int i; // 因为要在构造函数中进行初始化,所以此处便不可再赋值   final List list; // 因为要在构造函数中进行初始化,所以此处便不 可再赋值   Bat() {    i = 100;    list = new LinkedList();   }   Bat(int ii, List l) {    i = ii;    list = l;   }   public static void main(String[] args) {    Bat b = new Bat();    b.list.add(new Bat());    // b.i=25;    // b.list=new ArrayList();    System.out.println("I=" + b.i + " List Type:" + b.list.getClass());    b = new Bat(23, new ArrayList());    b.list.add(new Bat());    System.out.println("I=" + b.i + " List Type:" + b.list.getClass());   }}

结果:

I=100 List Type:class java.util.LinkedListI=23 List Type:class java.util.ArrayList

在main方法中有两行语句注释掉了,如果你去掉注释,程序便无法通过编译,这便是说, 不论是i的值或是list的类型,一旦初始化,确实无法再更改。然而b可以通过重新初始化来 指定i的值或list的类型。

1.2 final引用字段的无效初始化

要正确使用final字段有点麻烦,对于其构造子能抛出异常的对象引用来说尤其如此。因 为 final 字段在每个构造器中必须只初始化一次,如果 final 对象引用的构造器可能抛出 异常,编译器可能会报错,说该字段没有被初始化。编译器一般比较智能化,足以发现在两 个互斥代码分支(比如,if…else 块)的每个分支中的初始化恰好只进行了一次,但是它 对 try…catch 块通常不会如此“宽容”。

下面这段代码通常会出现问题。

class Thingie {   public static Thingie getDefaultThingie() {    return new Thingie();   }}public class Foo {   private final Thingie thingie;   public Foo() {    try {      thingie = new Thingie();    } catch (Exception e) {      thingie = Thingie.getDefaultThingie();//Error:The final field thingie may already have been assigned    }   }}

你可以这样修改。

public class Foo {   private final Thingie thingie;   public Foo() {    Thingie tempThingie;    try {      tempThingie = new Thingie();    } catch (Exception e) {      tempThingie = Thingie.getDefaultThingie();    }    thingie = tempThingie;   }}

1.3关于final成员使用

当你在类中定义变量时,在其前面加上final关键字,那便是说,这个变量一旦被初始化 便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对于对象变量来说其引 用不可再变。然而,对象其本身却是可以被修改的,Java并未提供使任何对象恒定不变的途 径。这一限制同样适合数组,它也是对象。

示例2

private final int VAL_ONE=9;private static final int VAL_TWO=99;public static final int VAL_THREE=999;

由于VAL_ONE 和VAL_TOW 是带有编译期数值的final 原始类型,所以它们二者均可以用作 编译期常量,并且没有重大区别。VAL_THREE是一种更加典型的对常量进行定义的方式:定义 为 public,则可以被用于包之外;定义为 static 来强调只有一份;定义为 final 来说明 它是一个常量。

final标记的变量即成为常量,但这个“常量”也只能在这个类的内部使用,不能在类的 外部直接使用。但是当我们用public static final 共同标记常量时,这个常量就成为全局 的常量(一个既是static又是final的字段只占据一段不能改变的存储空间)。而且这样定义 的常量只能在定义时赋值,其他地方都不行。

示例3

class Value {   int i;   public Value(int i) {    this.i = i;   }}public class FinalData {   private static Random rand = new Random();   private String id;   public FinalData(String id) {    this.id = id;   }   private final int i4 = rand.nextInt(20);   static final int i5 = rand.nextInt(20);   public String toString() {    return id + ":" + "i4:" + i4 + ", i5=" + i5;   }   public static void main(String[] args) {    FinalData fd1 = new FinalData("fd1");    System.out.println(fd1);    System.out.println(& 何愁没有快乐的泉溪在歌唱,何愁没有快乐的鲜花绽放!

Java关键字介绍之final

相关文章:

你感兴趣的文章:

标签云: