实例变量、静态变量、局部变量的生命周期
文章目录
- 前言
- 一、静态变量和实例变量的生命周期
- 二、局部变量的生命周期
- 三、总结
前言
本篇内容出自《Java面向对象编程:孙卫琴》第三章部分内容,目的是带你搞懂实例变量、静态变量、局部变量生命周期概念
一、静态变量和实例变量的生命周期
类的成员变量有两种:一种是被static关键字修饰的变量,叫类变量,或者静态变量,没有被static修饰的,叫实例变量
静态变量与实例变量的区别在于:
- 类的静态变量在内存中只有一个,Java虚拟机在加载类的过程中为静态变量分配内存,静态变量位于方法区,被类的所有实例共享。静态变量可以直接通过类名被访问。静态变量的生命周期取决于类的生命周期,当加载类的时候,静态变量被创建并分配内存,当卸载类的时候,静态变量被销毁并撤销内存。
- 类的每个实例都有相应的实例变量。每创建一个类的实例,Java虚拟机就会为实例变量分配一次内存,实例变量位于堆区中。实例变量的生命周期取决于实例的生命周期,当创建实例的时候,实例变量被创建并分配内存,当销毁实例的时候,实例变量被销毁并撤销内存。
以下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虚拟机的运行时数据区如图所示:
从图中我们就可以理解之前说的几个要点:
静态变量位于方法区,被类的所有实例共享。
所以静态变量count2在内存中只有一个,执行counterA.count2++或counterB.count2++实际上操纵的都是Counter类的同一个静态变量count2,即值为2;实例变量位于堆区中。
执行counterA.count1++实际上是由CounterA变量引用Counter实例的count1变量,和counterB引用的count1变量是不同的,所以各自的值都为1。
结合以前学过的基础知识,我们知道静态变量是可以直接通过 类名.变量 这种形式访问:
counterA.count1++; //通过counterA引用变量来访问count2变量
Counter.count2++; //通过Counter类名来访问count2变量
对于count1实例变量,是否可通Counter.count1(类名访问)访问呢?
答案显然是不行的,从图中我们看出,实例变量总是属于特定的实例的,Java虚拟机无法只通过类名就知道该访问到底是哪个实例中的变量。
二、局部变量的生命周期
什么是局部变量?
局部变量指的是在一个方法的内部
或者方法的一个代码块
中声明的变量,前者的作用域就是整个方法,后者的作用域则是这个代码块(代码块就是{}以内的代码)
大概了解了一下局部变量
概念,让我们看看它的生命周期。
局部变量的生命周期取决于所属的方法何时被调用及结束调用!
- 当Java虚拟机(更确切的说,是Java虚拟机中的某个线程)调用一个方法时,就会为这个方法中的局部变量分配内存。
- 当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”);会把其对象存储在堆,而把这个对象的引用(指针)存储在栈。
三、总结
静态变量的生命周期取决于类何时被加载及卸载;
实例变量的生命周期取决于实例何时被创建及销毁;
局部变量的生命周期取决于所属的方法何时被调用及结束调用。
参考链接:
https://blog.csdn.net/weixin_38756990/article/details/72857840
原文地址: https://blog.csdn.net/weixin_51201930/article/details/122922364
本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
相关文章