本篇文章主要借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爲何具備這些特性,望同行能在評論區點撥指正。