本篇内容出自《Java面向对象编程:孙卫琴》第三章部分内容,目的是带你搞懂实例变量、静态变量、局部变量生命周期概念
类的成员变量有两种:一种是被static关键字修饰的变量,叫类变量,或者静态变量,没有被static修饰的,叫实例变量
静态变量与实例变量的区别在于:
以下Counter类有两个成员变量,其中count1变量为实例变量,而count2变量为静态变量:
public class Counter {
public int count1 = 0; //count1 实例变量
public static int count2 = 0; //count2 静态变量
}
以下代码创建了两个Counter实例,然后分别修改它们的count1和count2变量:
Counter counterA = new Counter();
Counter counterB = new Counter();
counterA.count1++;
counterA.count2++;
counterB.count1++;
counterB.count2++;
执行以上代码后,Java虚拟机的运行时数据区如图所示:
从图中我们就可以理解之前说的几个要点:
结合以前学过的基础知识,我们知道静态变量是可以直接通过类名.变量这种形式访问:
counterA.count1++; //通过counterA引用变量来访问count2变量
Counter.count2++; //通过Counter类名来访问count2变量
对于count1实例变量,是否可通Counter.count1(类名访问)访问呢?
答案显然是不行的,从图中我们看出,实例变量总是属于特定的实例的,Java虚拟机无法只通过类名就知道该访问到底是哪个实例中的变量。
什么是局部变量?
局部变量指的是在一个方法的内部或者方法的一个代码块中声明的变量,前者的作用域就是整个方法,后者的作用域则是这个代码块(代码块就是{}以内的代码)
大概了解了一下局部变量概念,让我们看看它的生命周期。
局部变量的生命周期取决于所属的方法何时被调用及结束调用!
通过下面的代码例子来进一步了解局部变量的生命周期:
public class Sample {
int var1 =1; //var1是实例变量
static int var2=2; //var2是静态变量
public int add(){
int var3 = var1 +var2; //var3是局部变量
return var3;
}
public int delete(){
int var4 = var1 - var2; //var4是局部变量
return var4;
}
public static void main(String[] args) {
new Sample().add();
}
}
生命周期变化流程如下:
(1)加载Sample类,开始惊天变量var2的生命周期,var2位于方法区。
(2)创建Sample实例,开始实例变量var1的生命周期,var1位于堆区。
(3)调用Sample实例的add()方法,开始局部变量var3的生命周期,var3位于Java栈区
(4)执行完毕Sample实例的add()方法,结束局部变量var3的生命周期,退回到main()方法。
(5)执行完毕Sample类的main()方法,结束Sample实例及它的实例变量var1的生命周期,卸载Sample类,结束静态变量var2的生命周期,因此var4变量在Java虚拟机的运行过程中从没有被创建过。
由于局部变量和成员变量有着完全不同的生命周期,在使用局部变量时,受到以下限制:
1、局部变量不能被static、private、protected和public等修饰符修饰
因为局部变量本身就是一个访问权限的设定。只能在局部调用,也就是说局部变量的生命周期在{}之中除了这个方法外界是没办法访问你这个变量,所以不需要用任何修饰符修饰,比如private、public、protected等。但是能加final,也不能加static静态的关键词,因为static只能修饰成员变量和成员方法,在局部变量中用static修饰,又不能直接被类调用,而static关键字就是不直接过对象而用类就可以直接调用的,所以局部变量前不能加static关键字
2、不能通过类名或引用变量来访问局部变量
同理,局部变量的生命周期是在方法被调用期间存在的,作用域只在这个方法内,所以是无法被类名或引用变量来直接访问的。
扩展知识
对于局部变量,如果是基本类型,会把值直接存储在栈;如果是引用类型,比如String s = new String(“william”);会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。
静态变量的生命周期取决于类何时被加载及卸载;
实例变量的生命周期取决于实例何时被创建及销毁;
局部变量的生命周期取决于所属的方法何时被调用及结束调用。