您的位置:首页 > 编程语言 > Java开发

final类型变量的深入理解

2014-10-17 10:57 453 查看
大家都知道,final修饰的变量是不可改变值的,方法是不可被重写的,类是不可被继承的。

一直以来,我以为final修饰的变量一定是在定义时就初始化好,编译之后一直不变。原来final修饰的还有另一种变量,这种
情况在定义时并不能知道它的值。

下面详细分析一下:

final类型的变量一般还会选择用static的,因为final已经是不可改变的,那就可以在加载时就为其分配空间存储值。final修饰的变量分为以下两种情况,主要从调用其会不会造成类对象的初始化来看。

1)编译时可确定的;也就是说变量在定义时就明确初始化了。这种情况,当生成该对象的引用时,不会致使该类的初始化,因为在加载时已经将该变量的值存放在一个公共空间中。

2)编译时不可确定的,但在第一次使用之前一定要初始化,之后值就会一直保持不变。这种情况下,在不同的实例对象中,该final类型的变量可能会有不同的值。此时,生成一个该类的引用,若调用这种类型的变量,则会造成对象的初始化,才能知道该变量的值。

下面是个例子:

package com.ngnt.test.classInitialization;
import java.util.Random;

class TestSuper {
static {
System.out.println("Super Test class");
}
TestSuper() {
System.out.println("Super Test class constructor");
}
}

class Initable extends TestSuper {
static final int staticFinal = 123;
static final int staticFinal2 = TestClassInitialization.rand.nextInt(1000);
static {
System.out.println("Initailizing Initable class");
}
Initable() {
System.out.println("Initable class's constructor.");
}
}

class Initable2 {
static int staticNonFinal = 145;
static {
System.out.println("Initailizing Initable2 class");
}

Initable2() {
System.out.println("Initable2 class's constructor.");
}
}

class Initable3 {
static int staticNonFinal = 38;
static {
System.out.println("Initializing Initable3 class");
}

Initable3() {
System.out.println("Initable3 class's constructor.");
}
}

public class TestClassInitialization {
public static Random rand = new Random(47);
private final int a = 1;
public static void main(String[] ars) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class initable = Initable.class;
// initable.newInstance();
System.out.println("After creating Initable reference.");
// Does not trigger initialization
System.out.println(Initable.staticFinal);
// Does trigger initialization, first initialize super class
System.out.println(Initable.staticFinal2);
// Does trigger initailization
System.out.println(Initable2.staticNonFinal);
Class initable3 = Class.forName("com.ngnt.test.classInitialization.Initable3");
initable3.newInstance();
System.out.println("After creating Initable3 reference.");
System.out.println(Initable3.staticNonFinal);
}
}


提示:生成一个类的引用有两种方式:
1. Class.forName("类名"); 注意这里的类名要是完整路径的类名,而且注意大小写。这种情况得到的对象的引用会立即初始化该对象,就不会出现上面说的访问时初始化情况了。

2. 类名.class; 这种情况得到的对象的引用不会立即初始化该对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐