首頁 Java java教程 詳解Java程式設計中protected修飾符與static修飾符的作用

詳解Java程式設計中protected修飾符與static修飾符的作用

Jan 24, 2017 pm 03:32 PM

protected 
來談談protected存取權限問題。看下面範例1:
Test.java

class MyObject {}
  
public class Test {
  public static void main(String[] args) {
    MyObject obj = new MyObject();
    obj.clone(); // Compile error.
  }
}
登入後複製

此時出現上文提到的錯誤:The method clone from the type Object is not visiuable.
我們已經清楚Object.clone()是protected方法。這說明,該方法可以被同包(java.lang)下和它(java.lang.Object)的子類別存取。這裡是MyObject類別(預設繼承java.lang.Object)。
同樣Test也是java.lang.Object的子類別。但是,不能在一個子類別中存取另一個子類別的protected方法,儘管這兩個子類別繼承自同一個父類別。
再看範例2:
Test2.java

class MyObject2 {
  protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
  
public class Test2 {
  public static void main(String[] args) throws CloneNotSupportedException {
    MyObject2 obj = new MyObject2();
    obj.clone(); // Compile OK.
  }
}
登入後複製

這裡,我們在MyObject2類別中覆寫(override)父類別的clone()方法,在另一個類別Test2中呼叫clone()方法,編譯通過。
編譯通過的原因顯而易見,當你在MyObject2類別中覆寫clone()方法時,MyObject2類別和Test2類別在同一個套件下,所以此protected方法對Test2類別可見。
分析到這裡,我們在回憶一下Java中的淺複製與深複製文中,章節2.2中的聲明,②在派生類別中覆蓋基類的clone()方法,並聲明為public。現在明白這句話的原因了吧(為了讓它類別能呼叫這個類別的clone()方法,重載之後要把clone()方法的屬性設為public)。
下面再來看範例3:
Test3.java

package 1
class MyObject3 {
protected Object clone() throws CloneNotSupportedException {
    return super.clone();
  }
}
  
package 2
public class Test3 extends MyObject3 {
  public static void main(String args[]) {
    MyObject3 obj = new MyObject3();
    obj.clone(); // Compile error.
    Test3 tobj = new Test3();
    tobj.clone();// Complie OK.
  }
}
登入後複製

   

這裡我用Test3類別繼承MyObject3,注意這兩個類別是不同包裝的,否則就是範例2的情形。在Test3類別中呼叫Test3類別的實例tobj的clone()方法,編譯通過。而同樣呼叫MyObject3類別的實例obj的clone()方法,編譯錯誤!
意想不到的結果,protected方法不是可以被繼承類別存取嗎?
必須明確,類別Test3確實是繼承了類別MyObject3(包含它的clone方法),所以在類別Test3中可以呼叫自己的clone方法。但類別MyObject3的protected方法對其不同包子類別Test3來說,是不可見的。

方法的存取控制:

詳解Java程式設計中protected修飾符與static修飾符的作用

static
1.關鍵字static(先記住這些,再往下看)
1)靜態方法和靜態變數是屬於某一個類,而不是屬於類別的物件。
2)靜態方法和靜態變數的引用直接透過類別名稱引用。
3)在靜態方法中不能呼叫非靜態的方法和引用非靜態的成員變數。反之,則可以。
4)靜態變數在某種程式上與其他語言的全域變數相類似,如果不是私有的就可以在類別的外部進行存取。
2.何時使用static
在我們創建一個類別的實例時(物件),通常使用new方法,這樣這個類別的資料空間才會被創建,其方法才能被呼叫。
     但是,有時候我們希望一個類別雖然可以被創建n個物件(顯然這n個物件的資料空間是不相同的),但這n個物件的某些資料是相同的,即不管這個類別有多少的實例,這些資料對這些實例而言之有一份記憶體拷貝(見範例1)。這是靜態變數的情形。
另一種情形是,你希望某個方法不與包含它的類別的任何物件關聯在一起。也就是說,即使沒有建立對象,也能夠呼叫這個方法。 static 方法的一個重要用法就是在不建立任何物件的前提下,就可以呼叫它(請參閱範例2)。這是靜態方法的情況。
還有一種特殊的用法出現在內部類別中,通常一個普通類別不允許宣告為靜態的,只有一個內部類別才可以。這時這個宣告為靜態的內部類別可以直接當作一個普通類別來使用,而不需實例一個外部類別(見範例3)。這是靜態類別的情形。
範例1

public class TStatic {
  static int i;
  
  public TStatic() {
    i = 4;
  }
  
  public TStatic(int j) {
    i = j;
  }
  
  public static void main(String args[]) {
    System.out.println(TStatic.i);
    TStatic t = new TStatic(5); // 声明对象引用,并实例化。此时i=5
    System.out.println(t.i);
    TStatic tt = new TStatic(); // 声明对象引用,并实例化。此时i=4
    System.out.println(t.i);
    System.out.println(tt.i);
    System.out.println(t.i);
  }
}
登入後複製

結果:

0
5
4
4
4
登入後複製

static變數在類別被載入時創建,只要類別存在,static變數就存在。它們在定義時必須進行初始化。上例中沒有初始化i,所以會得到預設的初始值0。 static的變數的初始化僅能一次,static變數只是接受了最後一次的初始化。
實際這還是多個實例共享一個靜態的變數的問題。
 
範例2
未宣告為static

class ClassA {
  int b;
  
  public void ex1() {}
  
  class ClassB {
    void ex2() {
      int i;
      ClassA a = new ClassA();
      i = a.b; // 这里通过对象引用访问成员变量b
      a.ex1(); // 这里通过对象引用访问成员函数ex1
    }
  }
}
登入後複製

   

 
聲明為static

class ClassA {
  static int b;
  
  static void ex1() {}
}
  
class ClassB {
  void ex2() {
    int i;
    i = ClassA.b; // 这里通过类名访问成员变量b
    ClassA.ex1(); // 这里通过类名访问成员函数ex1
  }
}
登入後複製

   

在使用静态方法时要注意,在静态方法中不能调用非静态的方法和引用非静态的成员变量(在static方法中也不能以任何方式引用this或super)。理由很简单,对于静态的东西,JVM在加载类时,就在内存中开辟了这些静态的空间(所以可以直接通过类名引用),而此时非静态的方法和成员变量所在的类还没有实例化。
所以如果要使用非静态的方法和成员变量,可以直接在静态方法中实例化该方法或成员变量所在的类。public static void main就是这么干的。

示例3

public class StaticCls {
  public static void main(String[] args) {
    OuterCls.InnerCls oi = new OuterCls.InnerCls();// 这之前不需要new一个OuterCls
  }
}
  
class OuterCls {
  public static class InnerCls {
    InnerCls() {
      System.out.println("InnerCls");
    }
  }
}
登入後複製


结果:

InnerCls
登入後複製

3.静态初始化
static定义的变量会优先于任何其它非static变量,不论其出现的顺序如何。静态代码块(在“static{”后面跟着一段代码),是用来进行显式的静态变量初始化,这段代码只会初始化一次,且在类被第一次装载时。看下面示例。

class Value {
  static int c = 0;
  
  Value() {
    c = 15;
  }
  
  Value(int i) {
    c = i;
  }
  
  static void inc() {
    c++;
  }
}
  
class Count {
  public static void prt(String s) {
    System.out.println(s);
  }
  
  Value v = new Value(10);
  
  static Value v1, v2;
  static {
    prt("in the static block of calss Count v1.c=" + v1.c + " v2.c="
       + v2.c);
    v1 = new Value(27);
    prt("in the static block of calss Count v1.c=" + v1.c + " v2.c="
       + v2.c);
    v2 = new Value();
    prt("in the static block of calss Count v1.c=" + v1.c + " v2.c="
       + v2.c);
  }
}
  
public class TStaticBlock {
  public static void main(String[] args) {
    Count ct = new Count();
    Count.prt("in the main:");
    Count.prt("ct.c=" + ct.v.c);
    Count.prt("v1.c=" + Count.v1.c + " v2.c=" + Count.v2.c);
    Count.v1.inc();
    Count.prt("v1.c=" + Count.v1.c + " v2.c=" + Count.v2.c);
    Count.prt("ct.c=" + ct.v.c);
  }
}
登入後複製



结果:

in the static block of calss Count v1.c=0 v2.c=0
in the static block of calss Count v1.c=27 v2.c=27
in the static block of calss Count v1.c=15 v2.c=15
in the main:
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11
登入後複製

   

不管是v,v1还是v2,它们操作的成员变量都是同一个静态变量c。
在类Count中先初始化v1,v2(static Value v1, v2;),再初始化静态代码块(static{}),最后初始化v。

更多詳解Java程式設計中protected修飾符與static修飾符的作用相关文章请关注PHP中文网!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1664
14
CakePHP 教程
1423
52
Laravel 教程
1321
25
PHP教程
1269
29
C# 教程
1249
24
公司安全軟件導致應用無法運行?如何排查和解決? 公司安全軟件導致應用無法運行?如何排查和解決? Apr 19, 2025 pm 04:51 PM

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

如何將姓名轉換為數字以實現排序並保持群組中的一致性? 如何將姓名轉換為數字以實現排序並保持群組中的一致性? Apr 19, 2025 pm 11:30 PM

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

如何使用MapStruct簡化系統對接中的字段映射問題? 如何使用MapStruct簡化系統對接中的字段映射問題? Apr 19, 2025 pm 06:21 PM

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? IntelliJ IDEA是如何在不輸出日誌的情況下識別Spring Boot項目的端口號的? Apr 19, 2025 pm 11:45 PM

在使用IntelliJIDEAUltimate版本啟動Spring...

如何優雅地獲取實體類變量名構建數據庫查詢條件? 如何優雅地獲取實體類變量名構建數據庫查詢條件? Apr 19, 2025 pm 11:42 PM

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對像如何安全地轉換為數組? Java對像如何安全地轉換為數組? Apr 19, 2025 pm 11:33 PM

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? 電商平台SKU和SPU數據庫設計:如何兼顧用戶自定義屬性和無屬性商品? Apr 19, 2025 pm 11:27 PM

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...

如何利用Redis緩存方案高效實現產品排行榜列表的需求? 如何利用Redis緩存方案高效實現產品排行榜列表的需求? Apr 19, 2025 pm 11:36 PM

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

See all articles