首先是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 方法中引用任何執行個體變量都是非法的。