內部類
內部類的定義
將一個類定義在另一個給類里面或者方法里面,這樣的類就被稱為內部類。
內部類可以分為四種:成員內部類、局部內部類、匿名內部類、靜態內部類,下面我們逐一介紹這四種內部類。
成員內部類
他定義在另一個類中。一般定義格式如下
class C{
class D{
}
}
因為類C相對與類D在外面,我們且稱類C為外部類。
成員內部類可以無條件訪問外部類的屬性和方法,但是外部類想要訪問內部類屬性或方法時,必須要創建一個內部類對象,然后通過該對象訪問內部類的屬性或方法
成員內部類無條件訪問外部類的屬性和方法
class C{
private String name = "外部類";
public void run(){
System.out.println("外部類奔跑");
}
class D{
public void say(){
System.out.println(name);
run();
}
}
}
外部類訪問內部類屬性和方法
class C{
private String name = "外部類";
public void run(){
System.out.println("外部類奔跑");
}
/*使用內部類的屬性和方法*/
public void eat(){
D d = new D();
System.out.println(d.value);
d.say();
}
class D{
private String value = "DDD";
public void say(){
System.out.println(name);
run();
}
}
}
外部類屬性或方法隱藏
如果成員內部類的屬性或者方法與外部類的同名,將導致外部類的這些屬性與方法在內部類被隱藏,也可按照該格式調用,外部類.this.屬性/方法。
class C{
private String name = "外部類";
public void run(){
System.out.println("外部類奔跑");
}
/*使用內部類的屬性和方法*/
public void eat(){
D d = new D();
System.out.println(d.value);
d.say();
}
class D{
private String value = "DDD";
private String name = "內部類";
public void say(){
System.out.println(C.this.name);
System.out.println(name);
run();
}
}
}
創建內部類對象
顯然成員內部類是寄生於外部類,創建內部類對象就必須先創造外部類對象。之后創建內部類有兩種方式。
public class Test10 {
public static void main(String[] args) {
/*方式1創建成員內部類對象*/
C c = new C();
C.D d = c.new D();
/*方式2創建成員內部類對象*/
C.D d1 = c.getClassD();
}
}
class C{
private String name = "外部類";
public void run(){
System.out.println("外部類奔跑");
}
/*創建一個返回D對象的方法*/
public D getClassD(){
return new D();
}
/*使用內部類的屬性和方法*/
public void eat(){
D d = new D();
System.out.println(d.value);
d.say();
}
class D{
private String value = "DDD";
private String name = "內部類";
public void say(){
System.out.println(C.this.name);
System.out.println(name);
run();
}
}
}
成員內部類的訪問權限
成員內部類前可加上四種訪問修飾符。
private:僅外部類可訪問。
protected:同包下或繼承類可訪問。
default:同包下可訪問。
public:所有類可訪問。
局部內部類
局部內部類存在於方法中。
他和成員內部類的區別在於局部內部類的訪問權限僅限於方法或作用域內。
class K{
public void say(){
class J{
}
}
}
注意事項:局部內部類就像局部變量一樣,前面不能訪問修飾符以及static修飾符。
匿名內部類
下面我們先通過一段代碼初步了解一下匿名內部類。
public class Test13 {
public static void main(String[] args) {
driveCar(new Car(){
@Override
public void drive() {
System.out.println("駕駛着BMW汽車");
}
});
}
public static void driveCar(Car car){
car.drive();
}
}
interface Car {
void drive();
}
分析以上代碼知道靜態方法driveCar需要一個Car對象,我們通過實現接口創建一個匿名類對象傳遞過去。事實上還可以通過繼承類來創建一個匿名內部類對象。
注意事項:匿名內部類沒有構造方法。也是唯一沒有構造方法的內部類。匿名內部類和局部內部類只能訪問外部類的final變量。
靜態內部類
靜態內部類和成員內部類相比多了一個static修飾符。它與類的靜態成員變量一般,是不依賴於外部類的。同時靜態內部類也有它的特殊性。因為外部類加載時只會加載靜態域,所以靜態內部類不能使用外部類的非靜態變量與方法。
同時可以知道成員內部類里面是不能含靜態屬性或方法的。
class U {
static class I {
}
}
內部類的好處
- 完善了Java多繼承機制,由於每一個內部類都可以獨立的繼承接口或類,所以無論外部類是否繼承或實現了某個類或接口,對於內部類沒有影響。
- 方便寫事件驅動程序。
總結
public class Test15 {
public static void main(String[] args) {
//初始化bean1
Test15.Bean1 bean1 = new Test15().new Bean1();
bean1.i++;
//初始化bean2
Test15.Bean2 bean2 = new Test15.Bean2();
bean2.j++;
//初始化3
Bean bean = new Bean();
Bean.Bean3 bean3 = bean.new Bean3();
bean3.k++;
}
class Bean1 {
public int i = 0;
}
static class Bean2 {
public int j = 0;
}
}
class Bean {
class Bean3 {
public int k = 0;
}
}
靜態內部類對象的創建一般是外部類.內部類 類名 = new 外部類.內部類();
成員內部類對象的創建一般是外部類.內部類 類名 = 外部類對象名.new 內部類();
引用鏈接
如有侵權,告之立刪。