前言
由于平時(shí)使用內(nèi)部類不多烂琴,所以對(duì)內(nèi)部類只有一個(gè)很淺的認(rèn)知弧械。趁著春節(jié)有空蓉媳,整理了一些內(nèi)部類的使用筆記譬挚。
使用內(nèi)部類的好處
使用內(nèi)部類可以很好地解決多重繼承的問(wèn)題,每個(gè)內(nèi)部類都能獨(dú)立地繼承一個(gè)(接口的)實(shí)現(xiàn)督怜。
內(nèi)部類的分類
成員內(nèi)部類
靜態(tài)內(nèi)部類
方法內(nèi)部類
匿名內(nèi)部類
1.成員內(nèi)部類
private int num = 100;
String name = "zhou";
public class Inner{
String name = "Inner Zhou";
public void print(){
System.out.println(Demo.this.name); //當(dāng)內(nèi)部類屬性名和外部類屬性名一樣時(shí)殴瘦,外部類需要(外部類.this.屬性)來(lái)調(diào)用
System.out.println(name);//當(dāng)內(nèi)部類屬性名和外部類屬性名一樣時(shí),默認(rèn)調(diào)用內(nèi)部類屬性
System.out.println(num);
}
}
public static void main(String[] args){
Demo o = new Demo();
Inner in = o.new Inner();
in.print();
}
}
- 成員內(nèi)部類可以使用任意訪問(wèn)控制符号杠,如 public 蚪腋、 protected 丰歌、 private 等。
- 外部類可以直接訪問(wèn)成員內(nèi)部類中的數(shù)據(jù)屉凯,而不受訪問(wèn)控制符的影響立帖,如直接訪問(wèn)Demo類中的私有屬性num。
- 當(dāng)成員內(nèi)部類的屬性名和外部類的屬性名一樣時(shí)悠砚,默認(rèn)調(diào)用成員內(nèi)部類屬性晓勇。如上面代碼中,Demo類中的name屬性與Inner中name屬性名稱一樣灌旧,那么System.out.println(name);是默認(rèn)調(diào)用的是Inner的name屬性绑咱。
- 成員內(nèi)部類必須使用外部類對(duì)象來(lái)創(chuàng)建成員內(nèi)部類對(duì)象,而不能直接去 new 一個(gè)內(nèi)部類對(duì)象枢泰。即:內(nèi)部類 對(duì)象名 = 外部類對(duì)象.new 內(nèi)部類( )描融。
- 上述編譯程序后,會(huì)產(chǎn)生了兩個(gè) .class 文件: Demo.class,Demo$Inner.class{}衡蚂。
- 成員內(nèi)部類中不能存在任何static 的變量和方法,可以定義常量窿克。
2.靜態(tài)內(nèi)部類
private int num = 100;
String str = "zhou";
static String name = "zhou";
public static class Inner{
String name = "Inner Zhou";
public void print(){
System.out.println(new Demo().str);
System.out.println(Demo.name);
System.out.println(name);
}
}
public static void main(String[] args){
Inner in = new Inner();
in.print();
}
}
- 靜態(tài)內(nèi)部類不能直接訪問(wèn)外部類的非靜態(tài)成員,但可以通過(guò)【new 外部類().成員】 的方式訪問(wèn)
- 如果外部類的靜態(tài)成員與內(nèi)部類的成員名稱相同毛甲,可通過(guò)【類名.靜態(tài)成員】訪問(wèn)外部類的靜態(tài)成+ 員年叮,否則可通過(guò)【成員名】直接調(diào)用外部類的靜態(tài)成員。
- 創(chuàng)建靜態(tài)內(nèi)部類的對(duì)象時(shí)玻募,可以直接創(chuàng)建 內(nèi)部類 對(duì)象名 = new 內(nèi)部類();
3.方法內(nèi)部類
String a = "zhou a";
public void show() {
String b = "Zhou b";
class Inner {
String c = "Zhou c";
public void print(){
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
Inner i = new Inner();
i.print();
}
public static void main(String[] args) {
Demo demo = new Demo();
demo.show();
}
}
- 方法內(nèi)部類不能有 public只损、protected、private 以及 static 修飾符
- jdk8版本之前补箍,只能訪問(wèn)方法中定義的 final 類型的局部變量改执。
- jdk1.8版本之后啸蜜,新增了 Effectively final功能坑雅,方法內(nèi)部類和匿名內(nèi)部類中調(diào)用方法中的局部變量,可以不需要修飾為 final。下面是文檔的原話:
However, starting in Java SE 8, a local class can access local variables and parameters of the enclosing block that are final or effectively final. A variable or parameter whose value is never changed after it is initialized is effectively final.
- 4.反編譯jdk8編譯之后的class文件衬横,內(nèi)部類引用外部的局部變量都是 final 修飾的裹粤。
4.匿名內(nèi)部類
public InnerClass getInnerClass(String str){
return new InnerClass(){
{
a = 2; //利用構(gòu)造代碼塊能夠達(dá)到為匿名內(nèi)部類創(chuàng)建一個(gè)構(gòu)造器的效果
}
public String getStr(){
return str;
}
};
}
abstract class InnerClass {
int a;
abstract String getStr();
}
//也可以是接口
/*interface InnerClass{
String getStr();
}*/
public static void main(String[] args) {
Demo demo = new Demo();
InnerClass inner = demo.getInnerClass("zhou");
System.out.println(inner.getStr());
System.out.println(inner.a);
}
}
- 創(chuàng)建匿名內(nèi)部類時(shí)它會(huì)立即創(chuàng)建一個(gè)該類的實(shí)例。
- 使用匿名內(nèi)部類時(shí)蜂林,必須繼承一個(gè)類或者實(shí)現(xiàn)一個(gè)接口遥诉,但同時(shí)也只能繼承一個(gè)類或者實(shí)現(xiàn)一個(gè)接口。
- 匿名內(nèi)部類中不能定義構(gòu)造函數(shù)噪叙,不能存在任何的靜態(tài)成員變量和靜態(tài)方法矮锈。
- 匿名內(nèi)部類不能是抽象的,它必須要實(shí)現(xiàn)繼承的類或者實(shí)現(xiàn)的接口的所有抽象方法睁蕾。
- 匿名內(nèi)部類初始化:可以使用構(gòu)造代碼塊達(dá)到為匿名內(nèi)部類創(chuàng)建一個(gè)構(gòu)造器的效果苞笨。