Java基礎——static 靜靜地隨著類的載入而載入
static表示“全域性”或者“靜態”的意思,用來修飾成員變數和成員方法,也可以形成靜態static程式碼塊,但是Java語言中沒有全域性變數的概念。
簡單分的可以有這麼幾個類別
- static 變數
- static 方法
- static 程式碼塊
一、特點
-
1、隨著類的載入而載入,優先於物件存在,不依賴於類的例項,被所有物件所共享,也就是說——static的成員和方法可以被直接被類名呼叫
被static修飾的成員變數和成員方法獨立於該類的任何物件。也就是說,它不依賴類特定的例項,被類的所有例項共享。只要這個類被載入,Java虛擬機器就能根據類名在執行時資料區的方法區內定找到他們。因此,static物件可以在它的任何物件建立之前訪問,無需引用任何物件。
只要一個類的方法或者成員被static修飾,那麼就可以直接通過 類名.方法名 或者 類名.變數名 訪問。當然也可以被該類的例項呼叫。
-
2、static的方法僅能呼叫其他的static 方法,只能訪問static資料,不能以任何方式引用this 或super。
static有足夠的自由,但是隻能陪自由的人玩,隨著類的載入而載入,沒有this,meiyou super。
阿敏說:別的成員都是伴隨著物件存在的,static如果調不是static的東西不可能,不是一個等級,static在別人不在,怎麼一起工作?
-
3、通常一個普通類不允許宣告為靜態的(非法),只有內部類才可以。這時這個宣告為靜態的內部類可以直接作為一個普通類來使用,而不需例項一個外部類。
靜態類只允許是內部類,使用內部靜態類不需要例項化。
靜態內部類和非靜態內部類之間到底有什麼不同呢?下面是兩者間主要的不同。 (1)內部靜態類不需要有指向外部類的引用。但非靜態內部類需要持有對外部類的引用。()
(2)非靜態內部類能夠訪問外部類的靜態和非靜態成員。靜態類不能訪問外部類的非靜態成員。他只能訪問外部類的靜態成員。
(3)一個非靜態內部類不能脫離外部類實體被建立,一個非靜態內部類可以訪問外部類的資料和方法,因為他就在外部類裡面。
二、static與訪問修飾符
1、static與訪問修飾符
與public
用public修飾的static成員變數和成員方法本質是全域性變數和全域性方法
與private
static 變數前可以有private修飾,表示這個變數可以在類的靜態程式碼塊中,或者類的其他靜態成員方法中使用(當然也可以在非靜態成員方法中使用),但是不能在其他類中通過類名來直接引用,這一點很重要。實際上你需要搞明白,private是訪問許可權限定,static表示不要例項化就可以使用,這樣就容易理解多了。static前面加上其它訪問許可權關鍵字的效果也以此類推。
三、static變數
按照是否靜態的對類成員變數進行分類可分兩種:
- 一種是被static修飾的變數,叫靜態變數或類變數;
- 另一種是沒有被static修飾的變數,叫例項變數。
兩者的區別是:
靜態變數/類變數:
對於靜態變數在記憶體中只有一個拷貝(節省記憶體),JVM只為靜態分配一次記憶體,在載入類的過程中完成靜態變數的記憶體分配,可用類名直接訪問(方便),當然也可以通過物件來訪問(但是這是不推薦的)。
例項變數:
對於例項變數,每建立一個例項,就會為例項變數分配一次記憶體,例項變數可以在記憶體中有多個拷貝,互不影響。
四、static方法
- 靜態方法可以直接通過類名呼叫,
- 任何的例項也都可以呼叫,
- 靜態方法不能被繼承
- 靜態方法中不能用this和super關鍵字
(我不能例項化都可以存在,我this我幹嘛,我不能被繼承,你super我幹嘛) - 不能直接訪問所屬類的例項變數和例項方法,只能訪問所屬類的靜態成員變數和成員方法。
(因為例項成員與特定的物件關聯!) - 因為static方法獨立於任何例項,因此static方法不能是abstract,因為static方法要有方法體。
static方法可以是private,這個不衝突,訪問修飾符永遠只做訪問修飾符做的事情,但是標記為private的static方法在其他類中(包括子類)就不能通過 類名.方法名 呼叫了。
4、靜態程式碼塊
用static修飾的程式碼塊表示靜態程式碼塊,當Java虛擬機器(JVM)載入類時,就會執行該程式碼塊
五、證明
1、證明 類的所有例項共享同一個static變數
public class SpeClassTest {
static int num = 0;
}
.
.
一個物件改變static屬性的值,全部物件改變
import java.util.Arrays;
public class TestClass {
public static void main(String[] args) {
SpeClassTest spe1 = new SpeClassTest();
SpeClassTest spe2 = new SpeClassTest();
System.out.println("spe1 的成員值:"+spe1.num+" spe2 的成員值:"+spe2.num+"\n");
// 因為SpeClassTest裡面的num屬性是static的,所有物件共享,一個變則全部變
spe1.num = 3;
System.out.println("spe1 的成員值:"+spe1.num+" spe2 的成員值:"+spe2.num+"\n");
}
}
.
.
輸出
spe1 的成員值:0 spe2 的成員值:0
spe1 的成員值:3 spe2 的成員值:3
由此可以證明它們共享一塊儲存區。static變數有點類似於C中的全域性變數的概念。
2、靜態程式碼塊在類載入時載入,而且只執行一次,static定義的變數會優先於任何其它非static變數,不論其出現的順序如何
普通程式碼塊是在類初始化的時候載入
.
.
public class MyValue {
static int val = 0;
MyValue(){
val = 10;
}
MyValue(int i){
val = i;
}
void add(){
val = val+1;
}
}
.
.
import java.util.Arrays;
public class TestClass {
MyValue myValue = new MyValue(10);
static MyValue v1,v2;
static{
prt("v1.val "+v1.val+" v2.val:"+v2.val);
v1 = new MyValue(30);
prt("v1.val "+v1.val+" v2.val:"+v2.val);
v1 = new MyValue(40);
prt("v1.val "+v1.val+" v2.val:"+v2.val);
}
public static void main(String[] args) {
TestClass test = new TestClass();
prt("test.myValue.val: "+test.myValue.val);
prt("v1.val "+v1.val+" v2.val:"+v2.val);
v1.add();
prt("test.myValue.val: "+test.myValue.val);
prt("v1.val "+v1.val+" v2.val:"+v2.val);
}
public static void prt(String s) {
System.out.println(s);
}
}
.
輸出
v1.val 0 v2.val:0
v1.val 30 v2.val:30
v1.val 40 v2.val:40
test.myValue.val: 10
v1.val 10 v2.val:10
test.myValue.val: 11
v1.val 11 v2.val:11
分析:
開始的三句輸出,
v1.val 0 v2.val:0
v1.val 30 v2.val:30
v1.val 40 v2.val:40
是因為TestClass這個靜態程式碼塊隨著類的載入而載入導致的(如果我們把main方法的裡面的邏輯去掉,那麼只有前面的三句了)
重點是:static定義的變數會優先於任何其它非static變數,不論其出現的順序如何。正如在程式中所表現的,雖然myValue出現在v1和v2的前面,但是結果卻是v1和v2的初始化在myValue的前面
.
.
.
而第4句
test.myValue.val: 10
是因為main方法裡面TestClass test = new TestClass();這句執行,但是此時static程式碼塊已經記載過就不會再載入了,所以列印的是10.
(如果沒TestClass test = new TestClass();這一句,那麼肯定val的值還是40)
後面幾乎就沒什麼了,沒什麼特別的了。
3、static類只能是內部類,其他靜態類非法
public class StaticCls {
public static void main(String[] args) {
OuterCls.InnerCls oi = new OuterCls.InnerCls();
}
}
class OuterCls {
public static class InnerCls {
InnerCls() {
System.out.println("InnerCls");
}
}
}
結果為:InnerCls
.
.
.
下面程式碼演示 java中建立靜態內部類和非靜態內部類
/* 下面程式演示如何在java中建立靜態內部類和非靜態內部類 */
class OuterClass{
private static String msg = "GeeksForGeeks";
// 靜態內部類
public static class NestedStaticClass{
// 靜態內部類只能訪問外部類的靜態成員
public void printMessage() {
// 試著將msg改成非靜態的,這將導致編譯錯誤
System.out.println("Message from nested static class: " + msg);
}
}
// 非靜態內部類
public class InnerClass{
// 不管是靜態方法還是非靜態方法都可以在非靜態內部類中訪問
public void display(){
System.out.println("Message from non-static nested class: "+ msg);
}
}
}
class Main
{
// 怎麼建立靜態內部類和非靜態內部類的例項
public static void main(String args[]){
// 建立靜態內部類的例項
OuterClass.NestedStaticClass printer = new OuterClass.NestedStaticClass();
// 建立靜態內部類的非靜態方法
printer.printMessage();
// 為了建立非靜態內部類,我們需要外部類的例項
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
// 呼叫非靜態內部類的非靜態方法
inner.display();
// 我們也可以結合以上步驟,一步建立的內部類例項
OuterClass.InnerClass innerObject = new OuterClass().new InnerClass();
// 同樣我們現在可以呼叫內部類方法
innerObject.display();
}
}
六、static和final一塊用表示什麼
static final用來修飾成員變數和成員方法,可簡單理解為“全域性常量”!
對於變數,表示一旦給值就不可修改,並且通過類名可以訪問。
對於方法,表示不可覆蓋,並且可以通過類名直接訪問。
相關文章
- 字型隨著ProgressBar的載入而滾動
- Java基礎-類載入器以及載入機制Java
- Java基礎——深入理解類的載入Java
- Java基礎篇—Java類載入機制Java
- 7、靜態檔案的載入
- python入門基礎(14)--類的屬性、成員方法、靜態方法以及繼承、過載Python繼承
- Java | 靜態巢狀類(Static Nested Class)Java巢狀
- 為什麼Java中有三種基礎的類載入器?Java
- 靜態程式碼塊類載入時並不會執行
- SpringBoot-靜態資源載入-原始碼Spring Boot原始碼
- java類的載入過程Java
- 一個Java類的載入Java
- Java安全基礎之Java反射機制和ClassLoader類載入機制Java反射
- Java jvm 類載入 反射JavaJVM反射
- Java動態載入類Java
- java類載入機制Java
- Golang1.16 使用embed載入靜態檔案Golang
- 熱修復與外掛化基礎——Java與Android的類載入器JavaAndroid
- Java類載入器詳解Java
- Java父子類載入順序Java
- Java-JVM-類載入器JavaJVM
- springboot專案所有靜態資源無法載入Spring Boot
- 人生 就想靜靜找個地 坐著 然後輕輕地 嘆口氣
- 類載入
- 類與類的載入
- static靜態方法的使用
- 關於java中的類載入器Java
- ES6中類的靜態方法=> static 的使用
- JVM必備基礎知識(一) -- 類的載入機制JVM
- 類載入流程,類載入機制及自定義類載入器
- 類載入-載入時機學習
- Java類載入知識總結Java
- Java類載入原始碼閱讀Java原始碼
- 07.Java類載入問題Java
- Java類載入機制總結Java
- 談談 Java 類載入機制Java
- 【koa2】教你如何用中介軟體koa-static-router 搭建靜態資源伺服器,實現多路由載入靜態資源伺服器路由
- 類檔案的結構、JVM 的類載入過程、類載入機制、類載入器、雙親委派模型JVM模型
- 探祕類載入器和類載入機制