Java中关于静态变量的一个问题

public class Test {

    public static void main(String args[]) {
        System.out.println(new WithFinalFields());
        System.out.println(new WithFinalFields());
    }
}
class SelfCounter {
    private static int counter;
    private int id = counter++;
    public String toString() {
        return "SelfCounter: " + id;
    }
} 
class WithFinalFields {
    static final SelfCounter wffs = new SelfCounter();
    final SelfCounter wff = new SelfCounter();
    public String toString(){
        return "wff = "+wff+"\n wffs ="+wffs;
    }
}

首先给出一段代码,其中有两个类,一个类对象作为另一个类的成员变量。要求给出程序的结果,因为对于静态变量的理解不够深刻,并不知道这个程序的结果是什么,干脆找到结果对其分析一番。

wff = SelfCounter: 1
wffs =SelfCounter: 0
wff = SelfCounter: 2
wffs =SelfCounter: 0

我们发现主函数中定义了两个变量,但是两个变量的toString执行的结果并不一样,我们具体分析下。

首先创建第一个变量的时候,我们需要先加载WithFinalFields这个类,加载类的时候会初始化所有的static部分,包括常量,变量,还有static代码块。这个类中只有wffs为静态变量,那么我们需要先加载SelfCounter类,发现其中存在counter这个静态变量,没有显式赋值,那么根据java的特性,SelfCounter类中的counter的值就为0;这时实例化SelfCounter类,id为0,并且counter变为1。实例化结束,wffs的id为0,这是第一个结果。加载WithFinalFields的过程结束,开始实例化WithFinalFields,这时我们只需要初始化wff变量,因为wffs是静态变量,它已经在类加载的时候加载过了。实例化wff变量时,SelfCounter类已经被加载,我们只需要实例化wff变量就行,这时SelfCounter类中的counter为1,那么wff.id==1,SelfCounter类中counter变为2.第一个WithFinalFields变量实例化结束。

这时我们开始实例化第二个WithFinalFields变量,我们的两个类都已经被加载,无需再次加载。我们首先实例化的是wff变量,因为wffs是静态变量,无需被实例化,wffs的id仍然为0。我们继续实例化wff变量,wff.id==2,SelfCounter类中counter变为3。至此第二个WithFinalFields变量实例化结束,结果也明了了。

在这个程序里面,我并没有发现final的作用,主要作用的是static这个修饰。

在我第一次试着理解程序的时候,并不能理解为什么第二个WithFinalFields变量的id仍然为0,后来发现WithFinalFields类中的wffs为静态变量,它的只有一个,只占据一块内存,所以无论创建几个WithFinalFields变量,wffs只有一个,并且它的id是不会发生变化的,因为这个变量初始化只在WithFinalFields类被加载的时候,这个过程只有一次,wffs的id发生被初始化也只有一次。所以它的id是不会发生改变的。

final修饰的变量理论上是不可变的,wff的值理论上是不能被改变的,但它区别于wffs的地方在于它是被初始化两次的,不同的WithFinalFields变量中的wff是不同的变量,占据不同的内存地址,所以虽然不可变,但是对于两个不同变量,就不存在不可变的问题了。

这个问题的讨论源于论坛 [final与static final的区别] (http://bbs.csdn.net/topics/350037073),我的理解完全来自于这个帖子的回复,尤其是四楼的见解,只是整合了一番,作为学习笔记。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值