本篇文章主要借static修饰符,进一步的理解static与jvm之间联系。
1. 基本概念java
静态变量:声明独立于对象的静态变量,不管一个类实例化多少对象,静态变量只有一份拷贝,局部变量不能被声明。 静态方法:声明独立于对象的静态方法,静态方法不能使用类的非静态变量。
2. 做用jvm
方便在没有建立对象的状况下调用方法或变量。
3. 深层原理ide
为了解决上面的特性,首先咱们须要从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=pcspa
受限于MO_or浅薄的知识体系,并无很好的阐明static为何具备这些特性,望同行能在评论区点拨指正。