Java中的內(nèi)部類又分為非靜態(tài)內(nèi)部類(匿名內(nèi)部類也是非靜態(tài)的內(nèi)部類)和靜態(tài)內(nèi)部類惶傻,兩者與外部類的關(guān)系是不一樣的挖胃,創(chuàng)建的方式也不一樣辽剧。
1 非靜態(tài)內(nèi)部類
Java的非靜態(tài)內(nèi)部類在構(gòu)造的時候族淮,會將外部類的引用傳遞進(jìn)來椭迎,并且作為內(nèi)部類的一個屬性彰阴,因此瘾敢,內(nèi)部類會隱式地持有其外部類的引用。也就是非靜態(tài)內(nèi)部類在構(gòu)造的時候需要有一個外部類的實例傳遞進(jìn)來進(jìn)行構(gòu)造尿这,不能像普通的Java類那樣直接就可以通過 new來生成簇抵;一個簡單的例子如下:
1 import java.util.ArrayList;
2 import java.util.LinkedList;
3 import java.util.List;
4 import java.util.Queue;
5 import java.util.Scanner;
6
7 public class Main {
8
9 /**
10 * @param args
11 */
12 public int k=3;
13 private static String string="Java";
14 protected float j=1.5f;
15 public static void show(){
16 System.out.println("show");
17 }
18 private void add(){
19 System.out.println("add");
20 }
21 public static void main(String[] args) {
22 // TODO Auto-generated method stub
23 Main m=new Main();
24 //合法的非靜態(tài)內(nèi)部類的構(gòu)造方式
25 Child c=m.new Child();
26 //Child c=new Child() 這是不合法的構(gòu)造方式
27 c.test();
28
29 }
30 //內(nèi)部類Child
31 class Child{
32 public int i;
33 public void test(){
34 System.out.println("k=:"+k);
35 System.out.println("string:"+string);
36 add();
37 System.out.println("j=:"+j);
38 show();
39 }
40
41 }
42
43 }
并且非靜態(tài)的內(nèi)部類可以訪問外部類的所有成員變量與方法,包括靜態(tài)的成員變量與方法,執(zhí)行內(nèi)部類Child的test()方法就可以得到下面的結(jié)果:
1 k=:3
2 string:Java
3 add
4 j=:1.5
5 show
2 靜態(tài)內(nèi)部類
Java中的靜態(tài)內(nèi)部類在構(gòu)造的時候并不需要外部類的引用妻味,因此靜態(tài)的內(nèi)部類不會持有外部類的引用正压,并且靜態(tài)內(nèi)部類只能訪問外部類的靜態(tài)成員變量和方法。一個簡單的例子為(上面的代碼做一些簡單的改動):
public class Main {
2
3 /**
4 * @param args
5 */
6 public int k=3;
7 private static String string="Java";
8 protected float j=1.5f;
9 public static void show(){
10 System.out.println("show");
11 }
12 private void add(){
13 System.out.println("add");
14 }
15 public static void main(String[] args) {
16 // TODO Auto-generated method stub
17 Main m=new Main();
18 //Child c=m.new Childe();//非法
19 Child c=new Child();
20 c.test();
21
22 }
23 static class Child{
24 public int i;
25
26 public void test(){
27 // System.out.println("k=:"+k);//不能訪問外部類非靜態(tài)變量
28 System.out.println("string:"+string);
29 //add(); //不能訪問外部類的非靜態(tài)方法
30 // System.out.println("j=:"+j);
31 show();
32 }
33
34 }
35
36 }
從上面的代碼可以看到责球,靜態(tài)內(nèi)部類的創(chuàng)建方式與普通的Java類的創(chuàng)建方式一樣焦履,執(zhí)行第21行代碼就可以得到如下結(jié)果:
1 string:Java
2 show
3 雜談
Java的非靜態(tài)內(nèi)部類的這種創(chuàng)建方式拓劝,會隱式地持有外部類的引用,而且默認(rèn)情況下這個引用是強(qiáng)引用嘉裤,因此郑临,如果內(nèi)部類的生命周期長于外部類的生命周期,程序很容易就產(chǎn)生內(nèi)存泄漏(你認(rèn)為垃圾回收器會回收掉外部類的實例屑宠,但由于內(nèi)部類持有外部類的引用厢洞,導(dǎo)致垃圾回收器不能正常工作)。為了避免這種情況的發(fā)生典奉,你可以在內(nèi)部類的內(nèi)部顯示持有一個外部類的軟引用(或弱引用)躺翻,并通過構(gòu)造方法的方式傳遞進(jìn)來,在內(nèi)部類的使用過程中卫玖,先判斷一下外部類是否被回收公你;