學(xué)習(xí)Java的同學(xué)注意了?。?!
學(xué)習(xí)進(jìn)程中遇到甚么問(wèn)題或想獲得學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交換群,群號(hào)碼:183993990 我們1起學(xué)Java!
內(nèi)部類(lèi) ———定義在類(lèi)的內(nèi)部的類(lèi)
典型的情況是,內(nèi)部類(lèi)繼承自某個(gè)類(lèi)或?qū)崿F(xiàn)某個(gè)接口,內(nèi)部類(lèi)的代碼操作創(chuàng)建其的外圍類(lèi)的對(duì)象。所以你可以認(rèn)為內(nèi)部類(lèi)提供了某種進(jìn)入其外圍類(lèi)的窗口。
java中的內(nèi)部類(lèi)和接口加在1起,可以實(shí)現(xiàn)多繼承。
可使某些編碼根簡(jiǎn)潔。
隱藏你不想讓他人知道的操作。
使用內(nèi)部類(lèi)最吸引人的緣由是:
每一個(gè)內(nèi)部類(lèi)都能獨(dú)立地繼承自1個(gè)(接口的)實(shí)現(xiàn),所以不管外圍類(lèi)是不是已繼承了某個(gè)(接口的)實(shí)現(xiàn),對(duì)內(nèi)部類(lèi)都沒(méi)有影響。如果沒(méi)有內(nèi)部類(lèi)提供的可以繼承多個(gè)具體的或抽象的類(lèi)的能力,1些設(shè)計(jì)與編程問(wèn)題就很難解決。從這個(gè)角度看,內(nèi)部類(lèi)使很多重繼承的解決方案變得完全。接口解決了部份問(wèn)題,而內(nèi)部類(lèi)有效地實(shí)現(xiàn)了“多重繼承”。
內(nèi)部類(lèi)分為: 成員內(nèi)部類(lèi)、靜態(tài)嵌套類(lèi)、方法內(nèi)部類(lèi)、匿名內(nèi)部類(lèi)。
特點(diǎn):
1、內(nèi)部類(lèi)依然是1個(gè)獨(dú)立的類(lèi),在編譯以后內(nèi)部類(lèi)會(huì)被編譯成獨(dú)立的.class文件,但是前面冠之外部類(lèi)的類(lèi)命和$符號(hào)。
2、內(nèi)部類(lèi)可以直接或利用援用訪問(wèn)外部類(lèi)的屬性和方法,包括私有屬性和方法(但靜態(tài)內(nèi)部類(lèi)不能訪問(wèn)外部類(lèi)的非靜態(tài)成員變量和方法)。內(nèi)部類(lèi)所訪問(wèn)的外部屬性的值由構(gòu)造時(shí)的外部類(lèi)對(duì)象決定?! ?/span>
3、而外部類(lèi)要訪問(wèn)內(nèi)部類(lèi)的成員,則只能通過(guò)援用的方式進(jìn)行,可問(wèn)內(nèi)部類(lèi)所有成員
4、訪問(wèn)機(jī)制:
System.out.println(this.x);或System.out.println(x);//內(nèi)部類(lèi)訪問(wèn)內(nèi)部類(lèi)的成員變量或成員方法可用此方法。
System.out.println(OuterClass.this.x);//內(nèi)部類(lèi)訪問(wèn)外部類(lèi)的同名變量時(shí)可用此方法,如果沒(méi)有同名可用System.out.println(x);
5、內(nèi)部類(lèi)可使用任意的范圍限定:public/private/protected class InnerClass,且嚴(yán)格依照這幾種訪問(wèn)權(quán)限來(lái)控制內(nèi)部類(lèi)能使用的范圍。普通類(lèi)的范圍限定只可以是public或不加。
6、內(nèi)部類(lèi)的命名不允許與外部類(lèi) 重名,內(nèi)部類(lèi)可以繼承同級(jí)的內(nèi)部類(lèi),也可繼承其它類(lèi)(除內(nèi)部類(lèi)和外部類(lèi))。
7、內(nèi)部類(lèi)可以定義為接口,并且可以定義另外1個(gè)類(lèi)來(lái)實(shí)現(xiàn)它
8、內(nèi)部類(lèi)可以定義為抽象類(lèi),可以定義另外1個(gè)內(nèi)部類(lèi)繼承它
9、內(nèi)部類(lèi)使用static修飾,自動(dòng)升級(jí)為頂級(jí)類(lèi),外部類(lèi)不可以用static修飾,用OuterClass.InnerClass inner=new OuterClass.InnerClass();創(chuàng)建實(shí)例。內(nèi)部類(lèi)還可定義為final.
10、內(nèi)部類(lèi)可以再定義內(nèi)部類(lèi)(基本不用)
101、方法內(nèi)的內(nèi)部類(lèi):
方法內(nèi)的內(nèi)部類(lèi)不能加范圍限定(protected public private)
方法內(nèi)的內(nèi)部類(lèi)不能加static修飾符
方法內(nèi)的內(nèi)部類(lèi)只能在方法內(nèi)構(gòu)建其實(shí)例
方法內(nèi)的內(nèi)部類(lèi)如果訪問(wèn)方法局部變量,則此局部變量必須使用final修飾
1)靜態(tài)內(nèi)部類(lèi)(靜態(tài)嵌套類(lèi))
從技術(shù)上講,靜態(tài)嵌套類(lèi)不屬于內(nèi)部類(lèi)。由于內(nèi)部類(lèi)與外部類(lèi)同享1種特殊關(guān)系,更確切地說(shuō)是對(duì)實(shí)例的同享關(guān)系。而靜態(tài)嵌套類(lèi)則沒(méi)有上述關(guān)系。它只是位置在另外一個(gè)類(lèi)的內(nèi)部,因此也被稱(chēng)為頂級(jí)嵌套類(lèi)。
靜態(tài)的含義是該內(nèi)部類(lèi)可以像其他靜態(tài)成員1樣,沒(méi)有外部類(lèi)對(duì)象時(shí),也能夠訪問(wèn)它。靜態(tài)嵌套類(lèi)不能訪問(wèn)外部類(lèi)的成員和方法。
語(yǔ)法
1 package com.tarena.day13; 2 3 import com.tarena.day13.Foo.Koo; 4 /** 5 * 靜態(tài)類(lèi)內(nèi)部語(yǔ)法演示 6 */ 7 public class StaticInner { 8 public static void main(String[] args) { 9 Koo koo = new Koo(); 10 System.out.println(koo.add());//4 11 } 12 13 } 14 class Foo{ 15 int a = 1; 16 static int b = 3; 17 /** 靜態(tài)內(nèi)部類(lèi),作用域類(lèi)似于靜態(tài)變量,屬于類(lèi)的 */ 18 static class Koo{ 19 public int add(){ 20 //a ,不能訪問(wèn)a 21 return b+1; 22 } 23 } 24 }
2)成員內(nèi)部類(lèi)
* 1 成員內(nèi)部類(lèi)必須利用外部類(lèi)實(shí)例創(chuàng)建
* 2 成員內(nèi)部類(lèi)可以同享外部類(lèi)的實(shí)例變量
1 import com.tarena.day13.inn.Goo.Moo; 2 3 public class InnerClassDemo { 4 public static void main(String[] args) { 5 //Moo moo = new Moo(); //編譯毛病,必須創(chuàng)建Goo的實(shí)例 6 Goo goo = new Goo(); 7 Moo moo = goo.new Moo();//利用goo實(shí)例創(chuàng)建Moo實(shí)例 8 Moo moo1 = goo.new Moo(); 9 //moo和moo1同享同1個(gè)goo實(shí)例的實(shí)例變量 10 System.out.println(moo.add());//2 11 System.out.println(moo1.add());//2 12 Goo goo1 = new Goo(); 13 goo1.a = 8; 14 Moo m1 = goo1.new Moo(); 15 Moo m2 = goo1.new Moo(); 16 System.out.println(m1.add());//9 17 System.out.println(m2.add());//9 18 19 } 20 } 21 class Goo{ 22 int a = 1; 23 /**成員內(nèi)部類(lèi)*/ 24 class Moo{ 25 public int add(){ 26 return a+1; 27 } 28 } 29 }
3)局部?jī)?nèi)部類(lèi)(方法內(nèi)部類(lèi))
(1)、方法內(nèi)部類(lèi)只能在定義該內(nèi)部類(lèi)的方法內(nèi)實(shí)例化,不可以在此方法外對(duì)其實(shí)例化。
(2)、方法內(nèi)部類(lèi)對(duì)象不能使用該內(nèi)部類(lèi)所在方法的非final局部變量。
由于方法的局部變量位于棧上,只存在于該方法的生命期內(nèi)。當(dāng)1個(gè)方法結(jié)束,其棧結(jié)構(gòu)被刪除,局部變量成為歷史。但是該方法結(jié)束以后,在方法內(nèi)創(chuàng)建的內(nèi)部類(lèi)對(duì)象可能依然存在于堆中!例如,如果對(duì)它的援用被傳遞到其他某些代碼,并存儲(chǔ)在1個(gè)成員變量?jī)?nèi)。正由于不能保證局部變量的存活期和方法內(nèi)部類(lèi)對(duì)象的1樣長(zhǎng),所之內(nèi)部類(lèi)對(duì)象不能使用它們。用法
1 package com.tarena.day13.inn; 2 3 import java.util.Comparator; 4 5 /** 6 * 局部?jī)?nèi)部類(lèi) 7 */ 8 public class LocalInnerClassDemo { 9 public static void main(String[] args) { 10 int a = 5; 11 final int b = 5; 12 //局部?jī)?nèi)部類(lèi),定義在方法內(nèi)部,作用域類(lèi)似于局部變量 13 //僅僅在方法內(nèi)部可見(jiàn) 14 //在局部?jī)?nèi)部類(lèi)中可以訪問(wèn)方法中的局部final變量 15 class Foo{ 16 public int add(){ 17 return b;//正確 18 //return a;//編譯毛病 19 } 20 } 21 22 Foo foo = new Foo(); 23 //臨時(shí)的自定義比較規(guī)則 24 class ByLength implements Comparator<String>{ 25 public int compare(String o1,String o2){ 26 return o1.length()-o2.length(); 27 } 28 } 29 } 30 31 }
4)匿名內(nèi)部類(lèi)
顧名思義,沒(méi)著名字的內(nèi)部類(lèi)。表面上看起來(lái)它們似乎著名字,實(shí)際那不是它們的名字。
匿名內(nèi)部類(lèi)就是沒(méi)著名字的內(nèi)部類(lèi)。甚么情況下需要使用匿名內(nèi)部類(lèi)?如果滿(mǎn)足下面的1些條件,使用匿名內(nèi)部類(lèi)是比較適合的:
·類(lèi)在定義后馬上用到。
·類(lèi)非常小(SUN推薦是在4行代碼以下)
·給類(lèi)命名其實(shí)不會(huì)致使你的代碼更容易被理解
在使用匿名內(nèi)部類(lèi)時(shí),要記住以下幾個(gè)原則:
·匿名內(nèi)部類(lèi)不能有構(gòu)造方法。
·匿名內(nèi)部類(lèi)不能定義任何靜態(tài)成員、方法和類(lèi)。
·匿名內(nèi)部類(lèi)不能是public,protected,private,static。
·只能創(chuàng)建匿名內(nèi)部類(lèi)的1個(gè)實(shí)例。
·1個(gè)匿名內(nèi)部類(lèi)1定是在new的后面,用其隱含實(shí)現(xiàn)1個(gè)接口或?qū)崿F(xiàn)1個(gè)類(lèi)。
·因匿名內(nèi)部類(lèi)為局部?jī)?nèi)部類(lèi),所以局部?jī)?nèi)部類(lèi)的所有限制都對(duì)其生效。
A、繼承式的匿名內(nèi)部類(lèi)和接口式的匿名內(nèi)部類(lèi)。
1 import java.util.Arrays; 2 import java.util.Comparator; 3 4 /**匿名內(nèi)部類(lèi) 語(yǔ)法*/ 5 public class AnnInnerClass { 6 7 public static void main(String[] args) { 8 // TODO Auto-generated method stub 9 Yoo yoo = new Yoo();//創(chuàng)建Yoo的實(shí)例 10 Yoo y1 = new Yoo(){}; 11 //new Yoo(){}創(chuàng)建匿名類(lèi)實(shí)例 12 //匿名類(lèi)new Yoo(){}是繼承Yoo類(lèi),并且同時(shí)創(chuàng)建了對(duì)象 13 //new Yoo(){}是Yoo的子類(lèi)型,其中{}是類(lèi)體(class Body) 14 //類(lèi)體中可以定義任何類(lèi)內(nèi)的語(yǔ)法,如:屬性,方法,方法重載,方法覆蓋,等 15 //子類(lèi)型沒(méi)著名字,所以叫匿名類(lèi)! 16 Yoo y2 = new Yoo(){ 17 public String toString(){//方法重寫(xiě)(覆蓋) 18 return "y2"; //y2是子類(lèi)的實(shí)例 19 } 20 }; 21 System.out.println(y2);//"y2",調(diào)用了匿名類(lèi)對(duì)象toString() 22 //匿名內(nèi)部類(lèi)可以繼承/實(shí)現(xiàn) 于 類(lèi),抽象類(lèi),接口等 23 //依照繼承的語(yǔ)法,子類(lèi)型必須實(shí)現(xiàn)所有的抽象方法 24 25 //Xoo x = new Xoo(){};//編譯毛病,沒(méi)有實(shí)現(xiàn)方法 26 final int b = 5; 27 Xoo xoo = new Xoo(){ //是實(shí)現(xiàn)接口,并且創(chuàng)建匿名類(lèi)實(shí)例,不是創(chuàng)建接口對(duì)象 28 public int add(int a){//實(shí)現(xiàn)接口中的抽象方法 29 return a+b; //要訪問(wèn)局部變量b,只能訪問(wèn)final變量 30 } 31 }; 32 System.out.println(xoo.add(5));//10,調(diào)用對(duì)象的方法 33 //Comparator接口也能夠使用匿名類(lèi)的方式 34 Comparator<String> byLength = new Comparator<String>(){ 35 public int compare(String o1,String o2){ 36 return o1.length()-o2.length(); 37 38 } 39 }; 40 String[] names = {"Andy","Tom","Jerry"}; 41 Arrays.sort(names,byLength); 42 System.out.println(Arrays.toString(names)); 43 //也能夠這樣寫(xiě),工作中經(jīng)常使用 44 Arrays.sort(names,new Comparator<String>(){ 45 public int compare(String o1,String o2){ 46 return o1.length()-o2.length(); 47 } 48 }); 49 } 50 51 }
接口式的匿名內(nèi)部類(lèi)是實(shí)現(xiàn)了1個(gè)接口的匿名類(lèi)。而且只能實(shí)現(xiàn)1個(gè)接口。
B。參數(shù)式的匿名內(nèi)部類(lèi)。
1 class Bar{ 2 void doStuff(Foo f){ 3 } 4 } 5 interface Foo{ 6 void foo(); 7 } 8 class Test{ 9 static void go(){ 10 Bar b = new Bar(); 11 b.doStuff(new Foo(){ 12 public void foo(){ 13 System.out.println("foofy"); 14 } 15 }); 16 } 17 }
構(gòu)造內(nèi)部類(lèi)對(duì)象的方法有:
1、內(nèi)部類(lèi)在自己所處的外部類(lèi)的靜態(tài)方法內(nèi)構(gòu)建對(duì)象或在另外一個(gè)類(lèi)里構(gòu)造對(duì)象時(shí)利用以下情勢(shì):
(1)OuterClass out = new OuterClass();
OuterClass.InnerClass in = out.new InnerClass();
(2)OuterClass.InnerClass in=new OuterClass().new InnerClass();
其中OuterClass是外部類(lèi),InnerClass是內(nèi)部類(lèi)。
2、內(nèi)部類(lèi)在它所在的外部類(lèi)的非靜態(tài)方法里或定義為外部類(lèi)的成員變量時(shí),則可用以下方式來(lái)構(gòu)造對(duì)象:
InnerClass in = new InnerClass();
3、如果內(nèi)部類(lèi)為靜態(tài)類(lèi),則可用以下情勢(shì)來(lái)構(gòu)造函數(shù):
OuterClass.InnerClass in = new OuterClass.InnerClass();
無(wú)需再利用外部類(lèi)的對(duì)象來(lái)來(lái)構(gòu)造內(nèi)部類(lèi)對(duì)象,如果靜態(tài)內(nèi)部類(lèi)需要在靜態(tài)方法或其它類(lèi)中構(gòu)造對(duì)象就必須用上面的方式來(lái)初始化。
學(xué)習(xí)Java的同學(xué)注意了?。。?/span>
學(xué)習(xí)進(jìn)程中遇到甚么問(wèn)題或想獲得學(xué)習(xí)資源的話,歡迎加入Java學(xué)習(xí)交換群,群號(hào)碼:183993990 我們1起學(xué)Java!