一直記得java類中用protected修飾的成員是可以讓子類訪問的,但一直沒實際去操作一下。今天發現原來雖然子類可以訪問父類的protected成員,但還是不能用在子類中實例化一個父類對象的方式去訪問protected成員,需要使用this.x或this.x()的形式或者實例化子類去訪問(x代表成員變量或方法)
然而,靜態的用protected修飾的成員變量或成員方法又可以直接用類名.x或者類名.x()或者實例化的父類對象去訪問。
今天做Thinking in java的習題的時候又碰到了一個關於protected類型的內部類的問題,在這里一起記錄一下。
題目是第9章 inner class 的Exercise 6。要求在第一個包里創建一個interface,里面至少包含一個方法。在第二個包里創建一個類,這個類需要包含一個protected類型的內部類,並且這個內部類要實現在第一個包里創建的接口。在第三個包里要創建一個類,繼承第二個包里的那個類,並且寫一個方法創建一個第二個包里的內部類的對象,將這個對象向上轉型成第一個包里的接口並返回。以下是我寫的代碼:
一:接口Input,代表 輸入設備
1 package innerclass.exercise6; 2 3 public interface Input { 4 void inputInstruction(String s); 5 }
二:類Computer,里面有一個protected修飾的Mouse內部類(代表鼠標),並且Mouse實現Inout接口
package innerclass.exercise6.other; import innerclass.exercise6.Input; public class Computer { protected int i = 2; protected class Mouse implements Input { @Override public void inputInstruction(String s) { System.out.println("execute "+s); } } }
三:類Lenovo,繼承Computer類,在getComputetMouse()方法里試圖創建一個Computer.Mouse對象,並向上轉型為Input並返回。
package innerclass.exercise6.another; import innerclass.exercise6.Input; import innerclass.exercise6.other.Computer; public class Lenovo extends Computer { Input getComputerMouse() { this.i++; Input computerMouse = this.new Mouse(); return computerMouse; } public static void main(String[] args) { Lenovo lenovo = new Lenovo(); lenovo.getComputerMouse().inputInstruction("open fire"); } }
本以為沒啥問題,但
Input computerMouse = this.new Mouse();
這一行卻飄紅了,idea提示“'innerclass.exercise6.other.Computer.Mouse' has protected access in 'innerclass.exercise6.other.Computer'”
這我就很疑惑了,Lenovo作為Computer的子類,也能夠正常訪問同樣是protected類型的成員變量i,甚至我可以單單聲明一個Mouse類型的變量(但不實例化),為啥一
調用Mouse的構造方法就報錯呢?
后來看了別人的答案才發現,給Mouse加一個public的構造方法就可以了。原來,類的構造方法的訪問權限默認是和類的訪問權限一致的,由於Mouse是protected的訪問
權限,它的默認構造函數也就是protected的訪問權限,而Lenovo和Mouse既不處於同一個包中,又不是Mouse的子類,自然是無法訪問Mouse的protected權限的構造方
法的。所以要想在Lenovo中得到一個Mouse的對象,就需要自己給Mouse加一個public訪問權限的構造方法。
至於可以在Lenovo里單單聲明一個Mouse類型的變量,我認為是可以把Mouse和i一樣看作是Computer的成員變量,Lenovo作為Computer的子類,自然可以訪問到Computer
的protected權限的成員變量Mouse。(當然,這只是我自己這樣理解的,內部類跟成員變量應該還是有不同的吧)
另有一個知識點提一下,只有內部類才能用private或者protect去修飾,一般的類是只有public或者package(默認)訪問權限的。