国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務器之家 - 編程語言 - JAVA教程 - 從內存地址解析Java的static關鍵字的作用

從內存地址解析Java的static關鍵字的作用

2020-01-13 17:04孤傲蒼狼 JAVA教程

這篇文章主要介紹了從內存地址解析Java的static關鍵字的作用,包括靜態成員變量和靜態方法等重要內容,需要的朋友可以參考下

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

  以下面的例子為例說明

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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。

  此時的內存布局示意圖如下所示

從內存地址解析Java的static關鍵字的作用

接下來程序執行到:

?
1
Cat mimi = new Cat(“mimi”);

  這里,調用Cat類的構造方法Cat(String name),構造方法的定義如下:

?
1
2
3
4
5
6
7
Cat ( String name){
 
  this.name = name;
 
  id=sid++;
 
}

  調用時首先在棧內存里面分配一小塊內存mm,里面裝著可以找到在堆內存里面的Cat類的實例對象的地址,mm就是堆內存里面Cat類對象的引用對象。這個構造方法聲明有字符串類型的形參變量,所以這里把“mimi”作為實參傳遞到構造方法里面,由于字符串常量是分配在數據區存儲的,所以數據區里面多了一小塊內存用來存儲字符串“mimi”。此時的內存分布如下圖所示:

從內存地址解析Java的static關鍵字的作用

當調用構造方法時,首先在棧內存里面給形參name分配一小塊空間,名字叫name,接下來把”mimi”這個字符串作為實參傳遞給name,字符串也是一種引用類型,除了那四類8種基礎數據類型之外,其他所有的都是引用類型,所以可以認為字符串也是一個對象。所以這里相當于把”mimi”這個對象的引用傳遞給了name,所以現在name指向的是”mimi”。所以此時內存的布局如下圖所示:

從內存地址解析Java的static關鍵字的作用

接下來執行構造方法體里面的代碼:

?
1
this.name=name;

  這里的this指的是當前的對象,指的是堆內存里面的那只貓。這里把棧里面的name里面裝著的值傳遞給堆內存里面的cat對象的name屬性,所以此時這個name里面裝著的值也是可以找到位于數據區里面的字符串對象“mimi”的,此時這個name也是字符串對象“mimi”的一個引用對象,通過它的屬性值就可以找到位于數據區里面的字符串對象“mimi”。此時的內存分布如下圖所示:

從內存地址解析Java的static關鍵字的作用

接下來執行方法體內的另一句代碼:

?
1
id=sid++;

  這里是把sid的值傳遞給id,所以id的值是100,sid傳遞完以后,自己再加1,此時sid變成了101。此時的內存布局如下圖所示。

從內存地址解析Java的static關鍵字的作用

 到此,構造方法調用完畢,給這個構造方法分配的局部變量所占的內存空間全部都要消失,所以位于棧空間里面的name這塊內存消失了。棧內存里面指向數據區里面的字符串對象“mimi”的引用也消失了,此時只剩下堆內存里面的指向字符串對象“mimi”的引用沒有消失。此時的內存布局如下圖所示:

從內存地址解析Java的static關鍵字的作用

接下來執行:

?
1
Cat pipi = new Cat(“pipi”);

  這里是第二次調用構造方法Cat(),整個調用過程與第一次一樣,調用結束后,此時的內存布局如下圖所示:

從內存地址解析Java的static關鍵字的作用

最后兩句代碼是調用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 塊僅在該類被加載時執行一次。下面的例子顯示

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
的類有一個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 方法中引用任何實例變量都是非法的。
下面是該程序的輸出:

?
1
2
3
4
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,則必須通過對象來訪問。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 综合在线视频 | 国产区一区 | 黄色成人在线 | 国产韩国精品一区二区三区 | 日韩精品一区二区三区中文在线 | 一区二区三区视频免费在线观看 | 日日韩av| 久久一级| 国产视频一区二区在线 | 免费黄网视频 | 成人av观看| 成年人黄色免费视频 | 精品成人一区二区 | 亚洲精品久久久久久久久久久 | 爱操av | 韩日毛片 | 欧美日韩视频在线第一区 | 欧美成人性生活 | 97色在线视频| 国产一级片| 久草免费在线 | 国产精品一区二区久久 | 亚洲精品无 | 日本黄a三级三级三级 | 国产一区av在线 | 久久久精品天堂 | 国内精品嫩模av私拍在线观看 | 国产在线观看二区 | 国产精品久久久久久中文字 | 国产精品精品 | 久久久精品一区二区 | h片在线| 午夜成人免费视频 | 日本一区二区三区精品视频 | 欧美日韩久久久 | 日本久久影视 | 仙人掌旅馆在线观看 | 欧美在线小视频 | 青青国产视频 | 久久久久中文字幕 | 噜噜噜噜狠狠狠7777视频 |