程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 從內存地址解析Java的static症結字的感化

從內存地址解析Java的static症結字的感化

編輯:關於JAVA

從內存地址解析Java的static症結字的感化。本站提示廣大學習愛好者:(從內存地址解析Java的static症結字的感化)文章只能為提供參考,不一定能成為您想要的結果。以下是從內存地址解析Java的static症結字的感化正文


靜態成員變量與非靜態成員變量的差別

  以上面的例子為例解釋

package cn.galc.test;

public class Cat {

  /**
   * 靜態成員變量
   */
  private static int sid = 0;

  private String name;

  int id;

  Cat(String name) {
    this.name = name;
    id = sid++;
  }

  public void info() {
    System.out.println("My Name is " + name + ",NO." + id);
  }

  public static void main(String[] args) {
    Cat.sid = 100;
    Cat mimi = new Cat("mimi");
    Cat pipi = new Cat("pipi");
    mimi.info();
    pipi.info();
  }
}

經由過程畫內存剖析圖懂得全部法式的履行進程

  履行法式的第一句話:Cat.sid = 100;時,這裡的sid是一個靜態成員變量,靜態變量寄存在數據區(data seg),所以起首在數據區外面分派一小塊空間sid,第一句話履行完後,sid外面裝著一個值就是100。

  此時的內存結構表示圖以下所示

接上去法式履行到:

    Cat mimi = new Cat(“mimi”);

  這裡,挪用Cat類的結構辦法Cat(String name),結構辦法的界說以下:

    Cat ( String name){

      this.name = name;

      id=sid++;

    }

  挪用時起首在棧內存外面分派一小塊內存mm,外面裝著可以找到在堆內存外面的Cat類的實例對象的地址,mm就是堆內存外面Cat類對象的援用對象。這個結構辦法聲明有字符串類型的形參變量,所以這裡把“mimi”作為實參傳遞到結構辦法外面,因為字符串常量是分派在數據區存儲的,所以數據區外面多了一小塊內存用來存儲字符串“mimi”。此時的內存散布以下圖所示:

當挪用結構辦法時,起首在棧內存外面給形參name分派一小塊空間,名字叫name,接上去把”mimi”這個字符串作為實參傳遞給name,字符串也是一種援用類型,除那四類8種基本數據類型以外,其他一切的都是援用類型,所以可以以為字符串也是一個對象。所以這裡相當於把”mimi”這個對象的援用傳遞給了name,所以如今name指向的是”mimi”。所以此時內存的結構以下圖所示:

接上去履行結構辦法體外面的代碼:

    this.name=name;

  這裡的this指的是以後的對象,指的是堆內存外面的那只貓。這裡把棧外面的name外面裝著的值傳遞給堆內存外面的cat對象的name屬性,所以此時這個name外面裝著的值也是可以找到位於數據區外面的字符串對象“mimi”的,此時這個name也是字符串對象“mimi”的一個援用對象,經由過程它的屬性值便可以找到位於數據區外面的字符串對象“mimi”。此時的內存散布以下圖所示:

接上去履行辦法體內的另外一句代碼:

    id=sid++;

  這裡是把sid的值傳遞給id,所以id的值是100,sid傳遞完今後,本身再加1,此時sid釀成了101。此時的內存結構以下圖所示。

 到此,結構辦法挪用終了,給這個結構辦法分派的部分變量所占的內存空間全體都要消逝,所以位於棧空間外面的name這塊內存消逝了。棧內存外面指向數據區外面的字符串對象“mimi”的援用也消逝了,此時只剩下堆內存外面的指向字符串對象“mimi”的援用沒有消逝。此時的內存結構以下圖所示:

接上去履行:

Cat pipi = new Cat(“pipi”);

  這裡是第二次挪用結構辦法Cat(),全部挪用進程與第一次一樣,挪用停止後,此時的內存結構以下圖所示:

最初兩句代碼是挪用info()辦法打印出來,打印成果以下:

  

  經由過程這個法式,看出來了這個靜態成員變量sid的感化,它可以計數。每當有一只貓new出來的時刻,就給它記一個數。讓它本身往上加1。

  法式履行完後,內存中的全部結構就如上圖所示了。一向連續到main辦法挪用完成的前一刻。

  這裡挪用結構辦法Cat(String name) 創立出兩只貓,起首在棧內存外面分派兩小塊空間mimi和pipi,外面分離裝著可以找到這兩只貓的地址,mimi和pipi對應著堆內存外面的兩只貓的援用。這裡的結構辦法聲明有字符串類型的變量,字符串常量是分派在數據區外面的,所以這裡會把傳過去的字符串mimi和pipi都存儲到數據區外面。所以數據區外面分派有存儲字符串mimi和pipi的兩小塊內存,外面裝著字符串“mimi”和“pipi”,字符串也是援用類型,除那四類8種的基本數據類型以外,其他一切的數據類型都是援用類型。所以可以以為字符串也是一個對象。

  這裡是new了兩只貓出來,這兩只貓都有本身的id和name屬性,所以這裡的id和name都長短靜態成員變量,即沒有static潤飾。所以每new出一只新貓,這只新貓都有屬於它本身的id和name,即非靜態成員變量id和name是每個對象都有零丁的一份。但關於靜態成員變量來講,只要一份,不論new了若干個對象,哪怕不new對象,靜態成員變量在數據區也會保存一份。如這裡的sid一樣,sid寄存在數據區,不管new出來了若干只貓在堆內存外面,sid都只要一份,只在數據區保存一份。

  靜態成員變量是屬於全部類的,它不屬於專門的某個對象。那末若何拜訪這個靜態成員變量的值呢?起首第一點,任何一個對象都可以拜訪這個靜態的值,拜訪的時刻拜訪的都是統一塊內存。第二點,即使是沒有對象也能夠拜訪這個靜態的值,經由過程“類名.靜態成員變量名”來拜訪這個靜態的值,所以今後看到某一個類名加上“.”再加上前面有一個器械,那末前面這個器械必定是靜態的,如”System.out”,這裡就是經由過程類名(System類)再加上“.”來拜訪這個out的,所以這個out必定是靜態的。
假如一個類成員被聲明為static,它就可以夠在類的任何對象創立之前被拜訪,而不用援用任何對象。static 成員的最多見的例子是main( ) 。由於在法式開端履行時必需挪用main() ,所以它被聲明為static。
聲明為static的變量本質上就是全局變量。當聲明一個對象時,其實不發生static變量的拷貝,而是該類一切的實例變量共用統一個static變量,例如:聲明一個static的變量count作為new一個類實例的計數。聲明為static的辦法有以下幾條限制:
(1)、它們僅能挪用其他的static 辦法。
(2)、它們只能拜訪static數據。
(3)、它們不克不及以任何方法援用this 或super。
假如你須要經由過程盤算來初始化你的static變量,你可以聲明一個static塊,Static 塊僅在該類被加載時履行一次。上面的例子顯示

的類有一個static辦法,一些static變量,和一個static 初始化塊:
public class UserStatic { 
    static int a = 3; 
    static int b;  
    static void meth(int x) { 
      System.out.println("x = " + x); 
      System.out.println("a = " + a); 
      System.out.println("b = " + b);  
    }  
    static { 
      System.out.println("Static block initialized."); 
      b = a * 4;  
    }  
    public static void main(String args[]) { 
      meth(42);  
    } 
  }

一旦UseStatic 類被裝載,一切的static語句被運轉。起首,a被設置為3,接著static 塊履行(打印一條新聞),最初,b被初始化為a*4 或12。然後挪用main(),main() 挪用meth() ,把值42傳遞給x。3個println ( ) 語句援用兩個static變量a和b,和部分變量x 。
留意:在一個static 辦法中援用任何實例變量都長短法的。
上面是該法式的輸入:

Static block initialized. 
x = 42 
a = 3 
b = 12

在界說它們的類的裡面,static 辦法和變量能自力於任何對象而被應用。如許,你只需在類的名字前面加點號(.)運算符便可。例如,假如你願望從類裡面挪用一個static辦法,你可使用上面通用的格局:
classname.method( )
這裡,classname 是類的名字,在該類中界說static辦法。可以看到,這類格局與經由過程對象援用變量挪用非static辦法的格局相似。一個static變量可以以異樣的格局來拜訪——類名加點號運算符。這就是Java 若何完成全局功效和全局變量的一個掌握版本。
總結:
(1)、static成員是不克不及被其地點class創立的實例拜訪的。
(2)、假如不加static潤飾的成員是對象成員,也就是歸每一個對象一切的。
(3)、加static潤飾的成員是類成員,就是可以由一個類直接挪用,為一切對象共有的。
 
 
Java Static:作為潤飾符, 可以用來潤飾變量、辦法、代碼塊(但相對不克不及潤飾類)。

(1)、潤飾變量:
類的一切對象配合具有的一個屬性,也稱為類變量。這相似於C說話中的全局變量。類變量在類加載的時刻初始化,並且只被初始化一次。在法式中任何對象對靜態變量做修正,其他對象看到的是修正後的值。是以類變量可以用作計數器。別的,Java Static變量可以用類名直接拜訪,而不用須要對象。
(2)、潤飾辦法:
類的一切對象配合具有的一個功效,稱為靜態辦法。靜態辦法也能夠用類名直接拜訪,而不用須要對象。所以在靜態辦法裡不克不及直接拜訪非靜態變量和非靜態辦法,在Static辦法裡不克不及湧現this或許super等症結字。
(3)、潤飾Java代碼塊:
用static去潤飾類外面的一個自力的代碼塊,稱為靜態代碼塊。靜態代碼塊在類第一次被加載的時刻履行,並且只履行一次。靜態代碼塊沒著名字,是以不克不及顯式挪用,而只要在類加載的時刻由虛擬機來挪用。它重要用來完成一些初始化操作。
(4)、說說類加載:
JVM在第一次應用一個類時,會到classpath所指定的途徑裡去找這個類所對應的字節碼文件, 並讀進JVM保留起來,這個進程稱之為類加載。
可見,不管是變量,辦法,照樣代碼塊,只需用static潤飾,就是在類被加載時就曾經"預備好了",也就是可以被應用或許曾經被履行。都可以離開對象而履行。反之,假如沒有static,則必需經由過程對象來拜訪。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved