一、引言
本篇文章主要借static修饰符,进一步的理解static与jvm之间联系。
二、总结
1. 基本概念
静态变量:声明独立于对象的静态变量,无论一个类实例化多少对象,静态变量只有一份拷贝,局部变量不能被声明。
静态方法:声明独立于对象的静态方法,静态方法不能使用类的非静态变量。
2. 作用
方便在没有创建对象的情况下调用方法或变量。
3. 深层原理
为了阐明上面的特性,首先我们需要从jvm内存讲起,
先放一张java内存结构图,我们再通过案例分析static修饰的变量放在哪儿。
从上图可以看出,静态变量存放在方法区中,被所有线程共享的。
而堆中是存放实例对象的,这里简单的描述下堆、栈、方法区。
堆区:
1)存储的全部是对象,每个对象包含一个对应的class,用于接收操作指令。
2)jvm只有一个堆区(heap),并被所有线程共享,堆中不存放基本类型和对象应用,只存放实例化对象。
栈区:
1)栈分为三个部分:基本类型变量区、执行上下文、操作指令区。
2)每个线程包含一个独自的栈,栈中存放的为基本数据类型的对象与堆中实例对象的引用(地址指向堆中的实例对象)。
3)栈中的数据都是私有的,其他栈不能访问。
方法区:
1)也叫静态区,和堆区一样被所有线程共享,方法区中存放的为class和static变量。
2)所存放的数据在整个程序中都是唯一存在的。
简单描述了栈、堆、方法区后,我们再结合案例从内存角度去分析,static的特性是从何而来的。
public class OnePiece {
private static String captain;
private String mate;
public void showSeaman(){
System.out.println(captain + "和" + mate);
}
/**
* 静态方法不能调用非静态变量
*/
public static void viewSeanman() {
System.out.println(captain);
// System.out.println(mate);
}
public static void main(String[] args) {
OnePiece straw = new OnePiece();
OnePiece.captain = "路飞";
straw.mate = "索隆";
straw.showSeaman();
OnePiece redhair = new OnePiece();
// OnePiece.captain = "香克斯";
// redhair.mate = "本·贝克曼";
redhair.showSeaman();
}
}
/**
* 输出:
* 路飞和索隆
* 路飞和null
*/
接下来我们再从内存的角度看看。
从上面可以看到当我们调用方法时,因为实例对象在堆中,所以随着对象的销毁,成员变量也就消失了。
但由于静态变量是存在方法区中的,被所有线程共享,并不会随对象销毁而消失。这就解释了static所具有的特性。
三、参考
https://baijiahao.baidu.com/s?id=1636927461989417537&wfr=spider&for=pc
四、最后
受限于MO_or浅薄的知识体系,并没有很好的阐明static为什么具有这些特性,望同行能在评论区点拨指正。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。