【轉載】對java中public、static的理解

 

轉載自:對java中public、static的理解

首先是public 

在說明這四個關鍵字之前,我想就class之間的關係做一個簡單的定義,對於繼承自己的class,base class可以認爲他們都是自己的子女,而對於和自己一個目錄下的classes,認爲都是自己的朋友。

 

1、public:public表明該數據成員、成員函數是對所有用戶開放的,所有用戶都可以直接進行調用

 

2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。

 

3、protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。

作用域 當前類 同一package 子孫類 其他package 

public       √             √                √               √ 

protected √             √                √                × 

friendly     √             √                ×               × 

private     √              ×               ×                ×

不寫時默認爲friendly

然後是static

static在java中表示靜態

但是這個靜態又是什麼意思呢?

最開始接觸static的時候看書上的概念根本沒弄懂!

接觸有一段時間java了,在這裏面要總結一下我對static的理解:

(概念)static表示“全局”或者“靜態”的意思,用來修飾成員變量和成員方法,也可以形成靜態static代碼塊,但是Java語言中沒有全局變量的概念。

這句話是說,你會用到static修飾一些個變量、方法、方法塊什麼的,這是你用到static的地方;“但是,java中沒有全局變量的概念”,怎麼理解這句話?你時刻要記住java是一個面向對象的語言,萬事萬物皆對象,無論你做什麼都需要創建一個對象,然後再調用這個對象的方法,java怎麼能允許存在一個在全局都通用的“全局變量”的概念存在呢?所以java中壓根就沒有所謂的“全局變量”,但是沒有這個概念,不代表你不可以實現這個功能,java存在的目的就是讓人們使用它去達到人們想要的效果,所以static value就可以達到全局變量的作用,所以,你現在應該可以理解下面這句話了吧。

(概念)用public修飾的static成員變量和成員方法本質是全局變量和全局方法,當聲明它類的對象市,不生成static變量的副本,而是類的所有實例共享同一個static變量。

現在進一步理解下面兩段概念:

(概念)只要這個類被加載,Java虛擬機就能根據類名在運行時數據區的方法區內找到他們。因此,static對象可以在它的任何對象創建之前訪問,無需引用任何對象。

根據實際例子來理解這段概念,現在有兩個類,Demo1和Demo2。

此實例還包含對靜態方法的操作

public class Demo1 {
    public static int i = 1;
    public int j = 2;
    
    public static int getNumber(){
        return i;
//        這個return返回的是全局變量的i,即前面多創建的i
    }
    
    public int getDealNumber(int j){
        return j;
//        這個return返回的是所傳進來的參數,是(int j)這個東西
    }

}

 

public class Demo2 {
    public static void main(String args[]){
//        想要得到Demo1中的靜態的(即全局的)變量i,直接用類名引用就可以了
        int i = Demo1.i;
//        但是想要得到Demo1中的實例的變量j,我需要怎麼做呢?(此刻牢記java面向對象的思想!)
//        首先我要先new一個Demo1的對象,然後纔可以通過new出來的對象得到Demo1中的j
        Demo1 demo1 = new Demo1();
        int j = demo1.j;
//        同理,java中的static方法和非static方法都是一樣的區別
//        下面一行的方法是靜態的,我可以直接根據類名調用方法
        int ii = Demo1.getNumber();
//        但是想要調用實例的方法,就需要利用前面所new出來的Demo1的對象來調用了
        int jj = demo1.getDealNumber(1);
//        所以現在你可以理解上文紫色的定義了麼?
    }
}

(概念)用public修飾的static成員變量和成員方法本質是全局變量和全局方法,當聲明它類的對象市,不生成static變量的副本,而是類的所有實例共享同一個static變量。

弄懂了上面的代碼,這句定義是不是迎刃而解了呢?這裏面涉及到堆棧的問題,我現在還沒有整理,我會整理的,寫完這篇我馬上就要鞏固一下堆棧的知識,我認爲堆棧的知識很重要,如果你也是初學者,關注我吧,嘿嘿~

 

這裏說一下靜態變量和實例變量的區別:

兩者的區別是:
 對於靜態變量在內存中只有一個拷貝(節省內存),JVM只爲靜態分配一次內存,在加載類的過程中完成靜態變量的內存分配,可用類名直接訪問(方便),當然也可以通過對象來訪問(但是這是不推薦的)。
 對於實例變量,沒創建一個實例,就會爲實例變量分配一次內存,實例變量可以在內存中有多個拷貝,互不影響(靈活)。


所以一般在需要實現以下兩個功能時使用靜態變量:
在對象之間共享值時
 方便訪問變量時

現在理解一下靜態方法

2、靜態方法
靜態方法可以直接通過類名調用,任何的實例也都可以調用靜態方法。前面的代碼中有直接通過類名調用的例子
靜態方法中不能用this和super關鍵字,不能直接訪問所屬類的實例變量和實例方法(就是不帶static的成員變量和成員成員方法),只能訪問所屬類的靜態成員變量和成員方法。因爲實例成員與特定的對象關聯!就是java面向對象的思想,實例是你這個類本身的屬性,你會用這個本身的屬性去做一些事情,而這些事情不是固定的,不能像靜態方法一樣一成不變。換位思考,人是一個java類,手是類的實例方法,而人身上有手機,這個手機就是靜態方法;人只會用手去玩手機,你見過人用手機玩手麼?哈哈
因爲static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract。靜態方法是類內部的一類特殊方法,只有在需要時纔將對應的方法聲明成靜態的,一個類內部的方法一般都是非靜態的

怎麼理解上面這句定義呢?記住得了,哈哈。

3、static代碼塊

 static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先後順序依次執行它們,每個代碼塊只會被執行一次。例如:
 

public class Test5 {
private static int a;
private int b;

static{
Test5.a=3;
System.out.println(a);
Test5 t=new Test5();
t.f();
t.b=1000;
System.out.println(t.b);
}
static{
Test5.a=4;
System.out.println(a);
}
public static void main(String[] args) {
// TODO 自動生成方法存根
}
static{
Test5.a=5;
System.out.println(a);
}
public void f(){
System.out.println("hhahhahah");
}
}

 

運行結果:
3
hhahhahah
1000
4
5

 利用靜態代碼塊可以對一些static變量進行賦值,最後再看一眼這些例子,都一個static的main方法,這樣JVM在運行main方法的時候可以直接調用而不用創建實例。

還用我再說什麼麼?

有時你希望定義一個類成員,使它的使用完全獨立於該類的任何對象。通常情況下,類成員必須通過它的類的對象訪問,但是可以創建這樣一個成員,它能夠被它自己使用,而不必引用特定的實例。在成員的聲明前面加上關鍵字static(靜態的)就能創建這樣的成員。如果一個成員被聲明爲static,它就能夠在它的類的任何對象創建之前被訪問,而不必引用任何對象。你可以將方法和變量都聲明爲static。static 成員的最常見的例子是main( ) 。因爲在程序開始執行時必須調用main() ,所以它被聲明爲static。
如果讀不懂這句話就倒着念,就明白個大概了。

注意一下幾點

聲明爲static的變量實質上就是全局變量。當聲明一個對象時,並不產生static變量的拷貝,而是該類所有的實例變量共用同一個static變量。聲明爲static的方法有以下幾條限制:

它們僅能調用其他的static 方法。

它們只能訪問static數據。

它們不能以任何方式引用this 或super(關鍵字super 與繼承有關,在下一章中描述)。
如果你需要通過計算來初始化你的static變量,你可以聲明一個static塊,Static 塊僅在該類被加載時執行一次。

下面的例子顯示的類有一個static方法,一些static變量,以及一個static 初始化塊:

// Demonstrate static variables,methods,and blocks.

class UseStatic {
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 方法中引用任何實例變量都是非法的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章