Java 內部類

Java 內部類

所謂的內部類(Inner Class),顧名思義,就是將一個類定義在另外一個類的內部。一個類內部的類被稱之爲內部類。this

內部類基本語法

// Outer 爲外部類,Inner 爲內部類
public class Outer{
	class Inner{
		// ...
	}
}

內部類的主要特色:

  • 內部類能夠很好的實現隱藏,可使用 protectedprivate 修飾符
  • 內部類能夠直接訪問外部類的全部成員,包括私有成員
  • 外部類不能直接訪問內部類的成員,必須首先創建內部類的對象纔可訪問
  • 內部類能夠解決一些問題,好比間接地區實現多繼承。能夠避免修改接口而實現同一個類中兩種同名方法的調用

內部類間接實現多繼承
示例:code

public class MultiExtends{
	public static void main(String[] args){
		C c = new C();
		// 訪問 A 類中的 showA() 方法
		c.getInstanceA1();
		// 訪問 B 類中的 showB() 方法
		c.getInstanceB1();
	}
}
class A{
	public void showA(){
		System.out.println("A");
	}
}
class B{
	public void showB(){
		System.out.println("B");
	}
}
// 至關於同時繼承了 A 類和 B 類
class C{
	// 內部類 A1
	private class A1 extends A{
		public void showA(){
			// 繼承 A 類的 showA()方法
			supper.showA();
		}
	}
	// 內部類 B1
	private class B1 extends B{
		public void showB(){
			// 繼承 B 類的 showB()方法
			supper.showB();
		}
	}
	// 給外部提供訪問內部私有類 A1 內的方法 的接口
	public void getInstanceA1(){
		 new A1().showA();
	}
	// 給外部提供訪問內部私有類 B1 內的方法 的接口
	public void getInstanceB1(){
		 new B1().showB();
	}
}

內部類實現父類與接口中的同名方法
示例:對象

public class MutilExtendsImplement{
	public static void main(String[] args){
		Son son = new Son();
		// 訪問抽象父類的 show() 方法
		son.show();
		// 訪問接口中的 show() 方法
		son.showSonInner();
	}
}
// 抽象類
abstract class Parent{
	// 抽象類中的 show() 抽象方法
	public abstract void show();
}
// 接口
interface IShow{
	// 接口中的 show() 方法
	// public void show();
	public void show1();
}

// 這種作法是不容許的,由於 Parent 類和 IShow() 存在同名方法 show(), Son 類不知道該實現哪一個 show() 方法 ,除非 抽象父類或者接口任一個修改方法名
// Son 類繼承 Parent 類並實現 IShow 接口
class Son extends Parent implements IShow{
	// 實現抽象父類
	public void show(){
		...
	}
	// 接口中的方法名改成 show1()
	public void show1(){
		...
	}
}

// 若抽象父類和接口都不修改方法名,能夠由內部類來實現
// 抽象類
abstract class Parent{
	// 抽象類中的 show() 抽象方法
	public abstract void show();
}
// 接口
interface IShow{
	// 接口中的 show() 方法
	public void show();
}
class Son extends Parent{
	// 實現抽象父類的 show() 方法
	public void show(){
		System.out.println("抽象類中的 show() 方法");
	}
	// 定義一個內部類來實現 IShow 接口
	private class SonInner implements IShow{
		// 實現接口的 show() 方法
		public void show(){
			System.out.println("接口中的 show() 方法");
		}
	}
	// 提供給外部訪問私有內部類 SonInner 方法的接口
	public void showSonInner(){
		new SonInner.show();
	}
}

內部類的分類

  • 成員內部類
  • 靜態內部類
  • 匿名內部類
  • 局部內部類

成員內部類及應用

成員內部類特色:繼承

  • 成員內部類屬於外部類的實例成員,成員內部類能夠有public、private、default、protected 權限修飾符,在成員內部類中訪問外部類的成員方法和屬性,要使用「外部類名.this.成員方法」 和「外部類名.this.成員屬性」的形式。

注:若成員內部類與外部類有同名方法或同名屬性,成員內部類在訪問外部類的同名方法或屬性時要使用「外部類名.this.(外部)成員方法(屬性)」形式,若成員內部類訪問的是與外部內非同名的方法或屬性,直接使用「方法名」或「屬性名」訪問便可接口

  • 建立成員內部類的實例使用「外部類名.內部類名 實例名 = 外部類實例名.new 內部類構造方法(參數)」的形式
    成員內部類有如下限制
  • 成員內部類不能與外部類重名
  • 不能在成員內部類中定義 static 屬性、方法和類(static final 形式的常量定義除外)。由於一個成員內部類實例比必然與一個外部類實例關聯,static 成員徹底能夠移到其外部類中去
  • 外部類不能直接訪問成員內部類的方法和屬性,能夠在外部類中聲明並建立成員內部類的實例,再經過成員內部類的實例來訪問成員內部類的方法和屬性

示例:作用域

public class MenberInnerClass{
	// 程序主方法
	public static void main(String[] args){
		Outer outer = new Outer();
		// 建立內部成員類實例
		Outer.Inner innre = outer.new Inner();
	}
}
// 外部類 Outer
class Outer{
	// 外部類屬性
	private String name;
	private int number;
	// 外部類方法
	public void showOuter(){
		System.out.println(name);
		System.out.println(number);
		// 外部類不能直接訪問內部類的成員方法和屬性
		// System.out.println(number2);
		}
	// 內部類 Inner
	public class Inner{
	private String name;
	private int number2;
	// 在成員內部類中不能聲明靜態的成員,包括屬性和方法
	// public static int number3 = 30;
	// 在成員內部類中能夠聲明靜態的常量
	private static final int number3 = 30;
	public void showInner(){
		System.out.println(name);
		System.out.println(number2);
		// 內部類調用外部類成員
		System.out.println(Outer.this.name);
		// 內部類調用外部類方法
		Outer.this.showOuter();
		}
	}
}

靜態內部類及應用

靜態內部類特色get

  • 使用 static 修飾的成員內部類叫靜態內部類
  • 靜態內部類跟外部類沒有任何關係,只是在生成類名和類定義時有影響。靜態內部類能夠看做是與外部類平級的類。使用方式與外部類平級的類徹底相同
  • 建立靜態內部類的實例使用 外部類名.內部類名 實例名 = new 外部類名.內部類名(參數) 例如:Outer.Inner inner = new Outer.Inner();

靜態內部類有如下限制io

  • 靜態內部類名字不能與外部類重名
  • 靜態內部類不能訪問外部類中的非靜態的屬性和方法,外部類不能直接訪問內部類中的非靜態成員,可是能夠經過在外部類中構造內部類的實例,而後用實例來調用靜態內部類中的非靜態成員,外部類能夠直接訪問靜態內部類的靜態成員,以 靜態內部類.成員 的形式,例如:StaticInner.name

匿名內部類及應用

匿名內部類特色class

  • 匿名內部類是 沒有名稱 的內部類,沒辦法引用它們,必須在建立時做爲 new 語句的一部分來聲明並建立它們的實例
  • 匿名內部類必須繼承一個類(抽象的、非抽象的均可以)或者實現一個接口;若是父類(或者父接口)是抽象類,則匿名內部類必須實現其全部抽象方法
  • 匿名內部類中能夠定義代碼塊,用於實例的初始化,可是不能定義靜態代碼塊

匿名內部類語法變量

new interface/superclass() {//類體}

  • 這種形式的 new 語句聲明一個新的匿名類,它對一個給定的類進行擴展,或者實現一個給定的接口,並同時建立該匿名類的一個新實例

示例:

public class AnonymousInnerClass{
	public static void main(String[] args){
		Person person = new Person();
		// 利用匿名內部類實例化 Animail 的一個子類
		person.feed(new Animial(){
			// 實現抽象類中的抽象方法 eat()
			public void eat(){
				System.out.println("eating");
			}
		});
		// 利用匿名內部類實現接口 Animail
		persion.feed(new Animail(){
			public void move(){
				System.out.println("moving");
			}
		});
	}
}
class Person{
	// feed 方法傳入 Animial 對象執行 eat() 方法
	public void feed(Animail animail){
		animail.eat();
	}
}
// 抽象父類 Animail
abstract class Animail{
	// 抽象方法 eat()
	public abstract void eat();
}
// 接口 Animail
interface Animail{
	public void move();
}

局部內部類及應用

局部內部類特色

  • 定義在代碼塊、方法體內的類叫局部內部類
  • 局部內部類訪問外部類的屬性和方法使用 「外部類名.this.屬性名」 和 「外部類名.this.方法名(參數)」 的形式
  • 對外部世界徹底隱藏,只能在其做用域內生成對象

局部內部類有如下限制

  • 局部內部類不能加訪問修飾符,由於它們並非類成員
  • 成員內部類不能與外部類重名
  • 局部內部類訪問做用域內的局部變量,該局部變量須要使用 fianl 訪問修飾符

示例:

public class LocalInnerClass{
	public static void main(String[] args){
		Outer outer = new Outer();
		// 經過調用 Outer 的 showOuter() 方法來調用局部內部類 Inner
		outer.showOuter();
	}
}
class Outer{
	private String name = "tom";
	private int num1 = 10;
	public void showOuter(){
		// 局部變量
		int num2 = 20;
		// 局部內部類 Inner,定義在 showOuter() 方法中
		class Inner{
			private String name = "jack";
			private int num3 = 30;
			public void showInner(){
				System.out.println(name);
				System.out.println(num3);
			}
		}
		// 構造局部內部類的實例,只能在當前這個方法的做用域內構造
		Inner inner = new Inner();
		inner.showInner();
	}
}
相關文章
相關標籤/搜索