final类型变量的深入理解

大家都知道,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; 这种情况得到的对象的引用不会立即初始化该对象。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值