Java包範圍可見性

一笨正經的小屁孩發表於2017-10-11

概述

本文主要介紹Java中的完全限定名,包範圍可見性以及類從編譯到執行時完全限定名的確定和類連線的大致過程。下面就讓我們一起來看一下...

1.完全限定名

Java中類的完全限定名指的是帶有完整包名的類,比如String類是在java.lang下,它的完全限定名就是java.lang.String。完全限定名常見的是在import語句後面,大多數情況下,import後面跟的就是某個類的完全限定名,少數情況下,import後面會引入某個包下的所有類,比如java.lang.*,此時就不是某個類的完全限定名了。

2.包範圍可見性-訪問修飾符修飾的類

先看下面這張圖

包結構
包結構

說明:在這張圖中,Class2和Class4都是沒加訪問修飾符的類(預設),Class1,Animal,Class3這三個類都無法呼叫Class2和Class4,因為它們不屬於同一級包,比如Animal是在Class2和Class4的上級包,Class1是在package2同級的另一個包package1中,Class3是在package2的子包package3中。
在Java中,宣告類的時候,訪問修飾符只有兩種,參考程式碼如下:

public class Class1{
    ...
}

class Class2{
    ...
}複製程式碼

public修飾符表示任何包下都能夠訪問,而不加任何訪問修飾符的,即預設情況下,表示只能同級包內訪問。

3.包範圍可見性-類與類之間變數訪問的可見性

再看下面這張圖

包結構
包結構

Class2類中宣告瞭四個用不同訪問修飾符修飾的變數,如下:

Class2類
Class2類

下面是幾個不同的類對Class2中變數的呼叫情況:
首先是Class4

Class4中對Class2中例項變數的呼叫情況
Class4中對Class2中例項變數的呼叫情況

然後是Class1

Class1中對Class2中例項變數的呼叫情況
Class1中對Class2中例項變數的呼叫情況

再然後是Class3

Class3中對Class2中例項變數的呼叫情況
Class3中對Class2中例項變數的呼叫情況

通過上面幾張圖主要是想說明幾個處於不同包位置的沒有直接關係的類之間對例項變數的呼叫情況,小結論:

* 處於同級包下的類在呼叫另一個類中的變數的時候,除了private修飾的私有變數不能訪問外,其他修飾符修飾的變數都能訪問;
* 處於不同級包的類只能訪問public修飾的變數,其他都不能訪問。複製程式碼

好了,上面說的是類與類之間的訪問,接下來說一說繼承中的變數訪問情況...

4.包範圍可見性-類繼承

還是一樣的,先上圖:

包結構
包結構

在上文中有說明Class2中定義了四個不同訪問修飾符修飾的變數,Class5是繼承自Class2,下面來看一看Class5這個類中對Class2四個變數的訪問情況...

類Class5
類Class5

通過上面的截圖我們可以看到變數D是紅色的,也就是不能訪問,而D是private修飾符修飾的,所以到此也就證明了private修飾的變數只能在本類中使用,其他類或者子類都無法訪問,public修飾的變數在其他類和子類中都能被訪問(不管其他類是在同級包還是不在都能夠訪問),protected和default的區別就在於子類是否和父類在同級包中,protected修飾的變數子類在其他包中也可以訪問,但是default情況下的變數子類只能在同級包中才可以訪問。

注:類中方法(包括靜態方法)以及靜態變數的可見性和上面所述的例項變數的可見性情況相同,就不再一一列舉了。

5.完全限定名的確定和類連線

在Java中,Java程式碼的執行需要經過編譯和解釋這兩個基本步驟,Java程式碼的編譯是由Java編譯器來做的,把Java原始碼翻譯成位元組碼,通俗的講就是把.java檔案翻譯成.class檔案,在這個過程中有一個很重要的步驟,就是Java編譯器在編譯原始碼的時候,會確定類中引用的每個類的完全限定名,確定的方式是根據import語句和classpath,如果import語句後面跟的是類的完全限定名,那麼這個類的完全限定名就直接確定下來了,如果跟的是類似java.lang.*(模糊匯入)的語句,那麼Java編譯器會再根據classpath配置的路徑去找對應的父包,也就是lang包,再在父包下尋找對應的類,如果還有一個java.xxx.*的import語句,恰好類中引用的類名在這兩個包下都有,那麼Java就會提示編譯錯誤,因為編譯器不知道到底要用哪一個包下的類,也就是類的完全限定名確定不下來,因而報錯。當引用的類的完全限定名確定下來了之後,Java編譯後的位元組碼檔案開始在Java虛擬機器上跑,連線就發生在該階段,Java虛擬機器會根據在編譯階段確定下來的引用到的類的完全限定名在classpath路徑中尋找對應的類並載入,這樣程式碼就齊全了,可以正常的跑起來了...

6.總結

本文內容較為基礎,主要是這段時間在對Java基礎進行系統性的回顧,期間遇到的一些比較重要且容易忽略的知識點在此記錄下來,讓自己有一個更深刻的印象,內容如有不當之處,歡迎各位大佬批評指正!

相關文章