摘要:
# 在一個類別的內部,其成員(包括成員變數和成員方法)能否被其他類別所訪問,取決於該成員的修飾詞;而一個類別能否被其他類別所訪問,取決於該類別的修飾詞。 Java的類別成員存取權限修飾詞有四個類別:private,無(預設情況下,套件存取權限),protected 和 public,而其中只有套件存取權限和public才能修飾一個類別(內部類別除外)。特別地,許多的介紹Java的書籍對protected介紹的比較籠統,常常會對大家造成誤解。因此,本文重點揭示了 protected 關鍵字的內涵和用法,並介紹了一些其他的修飾符。
版權聲明:
本文原創作者:書呆子Rico
作者部落格網址:http://www.php.cn/
一. Package
關於包的使用,我們只需注意一點:在一個專案中,不可以有相同的兩個包名,也就是說,我們的套件名稱不能和專案中其他的套件名稱重複,這裡不但包含自訂套件名稱也包含專案所引用的類別庫的套件名稱。 看下面範例:
package java.lang;public class MyObject { public static void main(String[] args) throws CloneNotSupportedException { Object o = new Object(); System.out.println(o.hashCode()); } }
我們給自己的程式的套件名稱是 java.lang,事實上,我們知道 java.lang 是JDK使用的套件名稱。 程式可以正常編譯,但當我們執行程式時會有套件衝突警告並拋出「java.lang.SecurityException: Prohibited package name: java.lang」 例外,如下圖所示。
句## 句
在一個類別的內部,其成員(包括成員變數和成員方法)能否被其他類別所訪問,取決於該成員的修飾詞。 Java的類別成員存取權限修飾詞有四個類別:
private,無(預設情況下,套件存取權限),protected 和 public。 其權限控制如下表所示:
成員,兩者要區分開),其存取權限修飾詞僅有public 和「無」(即套件存取權)兩種,而沒有private 和protected(有一個特例,只有內部類別可以是private或protected的,關於內部類別進一步了解請見我的部落格《Java 內部類別綜述》)。 因此,對於非內部類,我們只能賦予其套件存取權限或是 public 。 如果你不希望其他任何人對該類別擁有存取權,你可以把所有的建構器都指定為 private,從而阻止任何人創建該類別的物件
。這時候,該類別的物件只能在其static 成員內部進行創建,這種情況有點像單例模式
,例如像下面的範例:-
class Test { // private Constructor! private Test() {} // Allow creation via static method: public static Test getTest() { return new Test(); } }
在上面所提到的四種修飾詞中,除protected 外,都很好理解和掌握,我們在此進行簡述:#### #public :######被public修飾的類別成員能被所有的類別直接存取;### private:被public修饰的类成员只能在定义它的类中被访问,其他类都访问不到。特别地,我们一般建议将成员变量设为private的,并为外界提供 getter/setter 去对成员变量进行访问,这种做法充分体现了Java面向对象的四大特性(封装,多态,继承,抽象)中的封装思想;
-
包访问权限:包访问权限就是Java中的默认的权限,具有包访问权限的类成员只能被同一包中的类访问。
由于 protected 关键字的真正内涵不太容易理解,我们将在下一节专门介绍 protected 关键字。
三. protected 关键字的真正内涵
很多的有关介绍Java语言的书籍 (包括《Java编程思想》),都对protected介绍的比较的简单,基本都是一句话,就是:被protected修饰的成员对于本包和其子类可见。这种说法有点太过含糊,常常会对大家造成误解。对于protected的成员,要分子类和超类是否在同一个包中两种情况看待,现以 protected方法的调用为例进行说明,protected的成员变量类似。
实质上,protected方法的调用是否合法(编译是否通过)关键是要看被调用的protected方法从根源上看所在的类对应的包与调用代码所在的类对应的包是否相同,若相同,则合法;否则,不合法。当然,无论如何,子类是可以访问继承而来的属于它自己的受保护方法的。
我们可以看下面例子进行了解。
1). 第一种情形:子类与基类不在同一个包中
//示例一package p1;public class Father1 { protected void f() {} // 父类Father1中的protected方法}package p1; public class Son1 extends Father {}package p11; public class Son11 extends Father{}package p1; public class Test1 { public static void main(String[] args) { Son1 son1 = new Son1(); son1.f(); // Compile OK,protected方法f()来自于Father1类,与 Test1类 在同一包p1中 son1.clone(); // Compile Error,protected方法clone()来自于Object类,与 Test1类不在同一包中 Son11 son = new Son11(); son11.f(); // Compile OK,虽然Son11类在包p11中,但protected方法f()来自于Father1类,与 Test1类在同一包p1中 son11.clone(); // Compile Error,protected方法clone()来自于Object类,与 Test1类不在同一包中 } }
在上面的示例中,类Father1、Son1 和 Test1 在同一个包p1下,类Son11在包p11下。但是我们知道,无论Son1类还是Son11类,它们的protected方法f()在根源上都来自于p1包中的类Father1,而由于Test1也在p1包中,因此f()方法对Test1类可见,编译通过。但由于Son1类和Son11类中的clone()方法在根源上均来自于java.lang包下的类Object,与 Test1类不在同一包中,因此clone()方法对Test1类不可见,编译不通过。
//示例二package p2; class MyObject2 {protected Object clone() throws CloneNotSupportedException { return super.clone(); } }package p22;public class Test2 extends MyObject2 { public static void main(String args[]) { MyObject2 obj = new MyObject2(); obj.clone(); // Compile Error,protected方法clone()来自于MyObject2类,与 Test2类 不在同一包p1中 Test2 tobj = new Test2(); tobj.clone();// Complie OK,虽然 protected方法clone()来自于MyObject2类,与 Test2类 不在同一包p1中,但Test2类作为MyObject2类的子类,是可以访问继承而来的属于它自己的受保护方法的。 } }
在上面的示例中,类MyObject2 和 类Test2 分别在包 p2 和 p22 下。因此,在类Test2中通过MyObject2的引用调用MyObject2的protected方法clone()时,由于类MyObject2 和 类Test2 不在同一包中而编译不通过。但是我们知道,虽然 类Test2 的protected方法clone()在根源上也来源于 类MyObject2,但是Test2类作为MyObject2类的子类,是可以访问继承而来的属于它自己的受保护方法的。
//示例三package p3; class MyObject3 extends Test3 { }package p33;public class Test3 { public static void main(String args[]) { MyObject3 obj = new MyObject3(); obj.clone(); // Compile OK,protected方法clone()来自于Test3类,而现在正是在Test3类中访问该方法 } }
在上面的示例中,类MyObject3 和 类Test3 分别在包 p3 和 p33 下。但是由于 MyObject3类的protected方法clone()在根源上来自于类Test3中,而现在正是在Test3类中访问该方法,因此编译通过,原理与示例一类似。
//示例四package p4; class MyObject4 extends Test4 { protected Object clone() throws CloneNotSupportedException { return super.clone(); } }package p44;public class Test4 { public static void main(String args[]) { MyObject4 obj = new MyObject4(); obj.clone(); // Compile Error,protected方法clone()来自于MyObject4类,而Test4类与MyObject4类不在同一个包中 } }
该示例与示例三很类似,唯一不同的是 类MyObject4 重写了从 类Test4 中继承过来的protected方法clone()。这样,MyObject4 的 protected方法clone()在根源上来自于类本身而非Test4类。而类MyObject4 和 类Test4 又不在同一包下,因此编译不通过。
2). 第二种情形:子类与基类在同一个包中
//示例五package p5; class MyObject5 { protected Object clone() throws CloneNotSupportedException { return super.clone(); } }public class Test5 { public static void main(String[] args) throws CloneNotSupportedException { MyObject5 obj = new MyObject5(); obj.clone(); // Compile OK,protected方法clone()来自于MyObject5类,而Test5类与MyObject5类又在同一个包中 } }
该示例与示例四很类似,唯一不同的是 类MyObject5 与 类Test5在同一个包p5中。正因为二者在同一包中,因此编译通过。
//示例六package p6; class MyObject6 extends Test6{}public class Test6 { public static void main(String[] args) { MyObject6 obj = new MyObject6(); obj.clone(); // Compile OK } }
在本示例中,由于类MyObject中的protected方法clone()从根源上来自于Test6类,而现在正是在 Test6 中调用protected方法clone(),因此编译通过。
//示例七package p7; class MyObject7 extends Test7 { public static void main(String[] args) { Test7 test = new Test7(); test.clone(); // Compile Error. } }public class Test {}
在本示例中,虽然类MyObject7与Test7类在同一个包p7中,但是由于 类Test7 的protected方法clone()从根源上来自于 java.lang.Object类,而其又与MyObject7不在同一个包中,因此编译不通过。
四. 其他的修饰符
static:修饰变量和内部类(不能修饰常规类),其中所修饰变量称为类变量或静态变量。静态变量是和类存在一起的,每个实例共享这个静态变量,在类加载时初始化。
final:被宣告為final的變數必須在宣告時給定初始值(當然,空白 final 情形除外),而且被修飾的變數不能修改值。當修飾類別時,該類別不能衍生出子類別;修飾方法時,該方法不能被子類別覆蓋。若讀者想對 final 有更深刻的了解,請移步我的博文 《Java 繼承、多態與類別的複用》。
abstract:修飾類別與方法。當修飾類別時,該類別不能建立物件;修飾方法時,為抽象方法。類別只要有一個abstract方法,類別就必須定義為abstract,但abstract類別不一定要有abstract方法不可。
#五. 總結
在一個類別的內部,其成員(包括成員變數和成員方法)能否被其他類別所訪問,取決於該成員的修飾詞;而一個類別能否被其他類所訪問,取決於該類的修飾詞。 Java的類別成員存取權限修飾詞有四個類別:private,無(預設情況下,套件存取權限),protected 和 public,而其中只有套件存取權限和public才能修飾一個類別(內部類別除外)。特別地,本文重點揭示了 protected 關鍵字的內涵和用法,並介紹了一些其他的修飾符。
六. 說明
在綜述本章的過程中,我們涉及到了很多知識點,其中有一些我們已經在其他博文中專門提到過,因此沒有作更多詳細的闡述,這裡給出對應的連結:
以上是Java存取權限控制-帶你詳細了解protected關鍵字(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器