java(四)內部類與多重繼承
內部類
定義:一個定義在類內部的類。之所以用內部類是因為使用內部類最吸引人的原因是:每個內部類都能獨立地繼承一個(介面的)實現,所以無論外圍類是否已經繼承了某個(介面的)實現,對於內部類都沒有影響。可以這樣說,介面只是解決了部分問題,而內部類使得多重繼承的解決方案變得更加完整。
內部類:內部類可以有多個例項,每個例項都有自己的狀態資訊,並且與其他外部物件的資訊相互獨立。在單個外部類中,可以讓多個內部類以不同的方式實現同一個介面,或者繼承同一個類。建立內部類物件的時刻並不依賴於外圍類物件的建立。內部類並沒有令人迷惑的“is-a”關係,他就是一個獨立的實體。內部類提供了更好的封裝,除了該外圍類,其他類都不能訪問。內部類與外部類建立一種關係,可以訪問外部類包括私有的屬性。引用內部類首先建立內部類物件要用外部類物件來建立,OuterClass.InnerClass innerClass = outerClass.new InnerClass();內部類與外部類是編譯時的概念,編譯之後就是兩個不同的class檔案,內部類分為成員內部類,區域性內部類、匿名內部類、靜態內部類。
成員內部類::1)成員內部類中不能存在任何static的變數和方法;2)成員內部類是依附於外圍類的,所以只有先建立了外圍類才能夠建立內部類。
public class Outer {
private String str;
public void outerDisplay(){
System.out.println("outer");
}
public class InnerClass{
public void innerDisplay(){
str = "ch";
System.out.println(str);
outerDisplay();
}
}
public InnerClass getInnerClass(){
return new InnerClass();
}
public static void main(String[] args) {
Outer outer = new Outer();
Outer.InnerClass inner = outer.getInnerClass();
inner.innerDisplay();
}
}
輸出ch 換行outer區域性內部類:巢狀在方法和作用域內,用來解決複雜問題不建立公共的,就所謂的區域性內部類,區域性內部類和成員內部類一樣被編譯,只是作用域發生了改變,只能在該方法和屬性內使用。
匿名內部類:Swing程式設計中,我們經常使用這種方式來繫結事件,
button2.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e) {
System.out.println("你按了按鈕二");
}
});
匿名內部類是沒有訪問修飾符的。new 匿名內部類,這個類首先是要存在的。當所在方法的形參需要被匿名內部類使用,那麼這個形參就必須為final。匿名內部類是沒有構造方法的。因為它連名字都沒有何來構造方法使用匿名內部類我們必須要繼承一個父類或者實現一個介面,當然也僅能只繼承一個父類或者實現一個介面。同時它也是沒有class關鍵字,這是因為匿名內部類是直接使用new來生成一個物件的引用。當然這個引用是隱式的。匿名內部類的使用它是存在一個缺陷的,就是它僅能被使用一次。建立匿名內部類時它會立即建立一個該類的例項,該類的定義會立即消失,所以匿名內部類是不能夠被重複使用,匿名內部類為區域性內部類,所以區域性內部類的所有限制同樣對匿名內部類生效。:匿名內部類不能是抽象的,它必須要實現繼承的類或者實現的介面的所有抽象方法。
當所在的方法的形參需要被內部類裡面使用時,該形參必須為final。內部類並不是直接呼叫方法傳遞的引數,而是利用自身的構造器對傳入的引數進行備份,自己內部方法呼叫的實際上時自己的屬性而不是外部方法傳遞進來的引數。內部類中我對屬性的改變並不會影響到外部的形參,所以為了保持引數的一致性,就規定使用final來避免形參的不改變。匿名內部類沒有構造器,使用構造程式碼塊達到創造一個構造器的效果。
靜態內部類:非靜態內部類在編譯完成之後會隱含地儲存著一個引用,該引用是指向建立它的外部類,但是靜態內部類卻沒有。沒有這個引用就意味著:它的建立是不需要依賴於外部類的。2)它不能使用任何外圍類的非static成員變數和方法。
public class Outer {
private String sex;
public static String name = "che";
static class InnerClass1{
/* 在靜態內部類中可以存在靜態成員 */
public static String _name1 = "che_static";
public void display(){
/*
* 靜態內部類只能訪問外圍類的靜態成員變數和方法
* 不能訪問外圍類的非靜態成員變數和方法
*/
System.out.println("OutClass name :" + name);
}
}
class InnerClass2{
/* 非靜態內部類中不能存在靜態成員 */
public String _name2 = "che_inner";
/* 非靜態內部類中可以呼叫外圍類的任何成員,不管是靜態的還是非靜態的 */
public void display(){
System.out.println("OuterClass name:" + name);
}
}
public void display(){
/* 外圍類訪問靜態內部類:內部類. */
System.out.println(InnerClass1._name1);
/* 靜態內部類 可以直接建立例項不需要依賴於外圍類 */
new InnerClass1().display();
/* 非靜態內部的建立需要依賴於外圍類 */
Outer.InnerClass2 inner2 = new Outer().new InnerClass2();
/* 方位非靜態內部類的成員需要使用非靜態內部類的例項 */
System.out.println(inner2._name2);
inner2.display();
}
public static void main(String[] args) {
Outer outer = new Outer();
outer.display();
}
}
輸出:che_static OutClass name :che che_inner OuterClass name:che多重繼承的實現
一個類可以同時從多個類繼承行為和屬性,java只支援單繼承,那麼實現多重繼承的方式有介面和內部類。
介面實現:介面和抽象類的時候瞭解到子類只能繼承一個父類,也就是說只能存在單一繼承,但是卻可以實現多個介面,介面是沒有任何具體實現的,也就是說,沒有任何與介面相關的儲存。
interface CanFight {
void fight();
}
interface Swim {
void swim();
}
interface Fly {
void fly();
}
public class Action {
public void fight(){
}
}
public class Hero extends Action implements Fight,Fly,Swim{
public void fly() {
}
public void swim() {
}
/**
* 對於fight()方法,繼承父類的,所以不需要顯示宣告
*/
}
內部類實現多繼承:
如果父類為抽象類或者具體類,那麼我就僅能通過內部類來實現多重繼承了。
class Father {
public int str(){
return 2;
}
}
class Mother {
public int can(){
return 2;
}
}
class Son {
class Father_1 extends Father{
public int str(){
return super.str() + 1;
}
}
class Mother_1 extends Mother{
public int can(){
return super.can() - 2;
}
}
public int get(){
return new Father_1().str();
}
public int getcan(){
return new Mother_1().can();
}
}
public class Outer {
public static void main(String[] args) {
Son son = new Son();
System.out.println( son.get());
System.out.println( son.getcan());
}
}
輸出3 0,定義兩個內部類,他們分別繼承父親Father類、母親類Mother類,且都可以非常獲取各自父類的行為,這是內部類一個重要的特性:內部類可以繼承一個與外部類無關的類,保證了內部類的獨立性,正是基於這一點,多重繼承才會成為可能。