java中关于static 类型的变量声明与初始化的问题

时间:2022-09-10 09:31:18
今天在聊天室看到这样一个问题,刚是感觉头脑一下 懵住了,现在简单整理一下,希望能对像我一样的广大菜鸟们解一份疑、答一份惑!
【问题】static int i = 1;中变量i被赋值几次?
首先,我们来弄清楚这样一个问题:静态变量在什么时候被加载?
    静态变量的声明与初始化是两个不同的操作,静态变量在编译的时候就明确了在内存中的位置,在类名第一次使用的时候,静态变量被加载, 由于静态变量的声明在编译时已经明确,所以静态变量的声明与初始化在编码顺序上可以颠倒。也就是说可以先编写初始化的代码,再编写声明代码,例如:
public static int i = 1;
等价于
public static int i;
static{
i = 1;
}
也可以写成:
static{
i = 1;
}
public static int i;

同时引出这样一个问题:
public class Test{
static{
i=20;
}
pulbic static int i = 10;
public void main(String ... args){
System.out.println(i);
}
static{
i = 30;
}
}
该问题等价于:
public class Test{
public static int i;
static{
i = 10;
i = 20;
i = 30;
}
main(){//函数省略}
}
因此输出的值是30。
注意:由于静态变量的声明与初始化时两个不同的操作,所以其顺序不影响结果,但是单个操作的时候就有顺序的区别了,也就是static{}静态代码块初始化的时候是有顺序的,同时系统在处理不同的初始化操作时,会将其放在一个static代码块中做统一处理。
故:
public class Test{
static{
i=10;
}
public static int i = 20;
public void main(String ... args){
System.out.println(i);
}
}
输出的值是:20

其次什么情况下才初始化的问题:
当类的定义中不含有static块时,编译器会为该类提供一个默认的static块。当然这是在含有静态变量初始化操作的前提下。例如:
public class Test{
public static int i = 20;
}
等价于:
public class Test{
public static int i;
static{
i = 20;
}
}
如果静态变量没有初始化操作,则编译器不会为之提供默认的static块。例如:
public class Test{
public static int i ;//在此仅仅是声明,并没有初始化数据
}
这时又引出另为一个问题,那就是:

public class Test{
public static int i ;
public void main(String ...args){
System.out.println(i);
}
}
输出的值是:0;
解释:在main函数没调用之前i是没有被初始化的,当main函数加载到内存中的栈中的时候,变量i同时被加载到内存的堆中,而堆中的变量是有初值的(整形数据初值为0,引用类型初始值为null)。java虚拟机在处理此类问题是有自己的一套机制,再次不做过多解释.

现在回到开始的问题上来:
public static int i = 1;
只被赋值了一次

【static的特点】
1、static是一个修饰符,用于修饰成员
2、static修饰的成员被所有实例化的成员共享
3、static优于对象存在,因为static的成员随着类的加载就已经存在了
4、static修饰的成员可以通过类名直接调用(类名.静态变量),当然也可以通过对象名调用
5、static修饰的数据是共享数据,对象中的存储是特有数据

另外,如果static修饰的静态变量放在类中,static修饰的变量在构造函数之前分配内存,这个成员是用于实例化的各个对象共享数据用的,所以构造函数不能使用静态成员,即堆中只存在一个静态成员,而不能实例化,这样说好像更好理解一些


注:本文是小编通过借鉴、膜拜、瞻仰了众大神的知识精华,再加上自己的理解和肤浅的知识储备而构思了这边博文,也存在个人能力所限所不能解释的知识模块,在此希望读者给予慷慨谅解,同时也可能存在一些与真知相违背的地方,在此小编深情的恳请您能够留下您宝贵的指正,本人将不胜受恩感激! java中关于static 类型的变量声明与初始化的问题