內(nèi)部類
Java 允許我們?cè)陬惖膬?nèi)部定義一個(gè)類。如果這個(gè)類是沒有 static
修飾符鸟款,那么這樣一個(gè)嵌套在內(nèi)部的類稱為 內(nèi)部類(inner class)。
內(nèi)部類被認(rèn)為是外部對(duì)象的一個(gè)成員茂卦。在定義內(nèi)部類時(shí)何什,我們同樣有訪問(wèn)權(quán)限控制(public,private等龙,protected)处渣。
在使用內(nèi)部類時(shí),我們要先創(chuàng)建外部對(duì)象蛛砰。由于內(nèi)部類是外部對(duì)象的一個(gè)成員罐栈,我們可以在對(duì)象的內(nèi)部自由使用內(nèi)部類:
class Human
{
private Cup myCup;
private String name;
public Human(String n)
{
this.myCup = new Cup();
this.name = n;
}
public void drinkWater(double w)
{
myCup.useCup(w);
System.out.println(myCup.getWater());
}
// 內(nèi)部類
private class Cup
{
public void useCup(double w)
{
this.water = this.water - w;
}
public double getWater()
{
return this.water;
}
private double water = 1.0;
}
}
public class Test
{
public static void main(String[] args)
{
Human me = new Human("Vamei");
me.drinkWater(0.3);
}
}
輸出:
0.7
上面的例子中,Cup
類為內(nèi)部類泥畅。該內(nèi)部類有 private
的訪問(wèn)權(quán)限荠诬,因此只能在 Human
內(nèi)部使用。這樣位仁,Cup
類就成為一個(gè)被 Human
類專用的類柑贞。
如果我們使用其他訪問(wèn)權(quán)限,內(nèi)部類也能從外部訪問(wèn)聂抢,比如:
class Human
{
private Cup myCup;
private String name;
// 構(gòu)造器
public Human(String n)
{
this.myCup = new Cup();
this.name = n;
}
public void drinkWater(double w)
{
myCup.useCup(w);
System.out.println(myCup.getWater());
}
// 內(nèi)部類
class Cup
{
public void useCup(double w)
{
this.water = this.water - w;
}
public double getWater()
{
return this.water;
}
private double water = 1.0;
}
}
public class Test
{
public static void main(String[] args)
{
Human me = new Human("Vamei");
me.drinkWater(0.3);
Human.Cup soloCup = me.new Cup(); // 在外部調(diào)用內(nèi)部類
}
}
這里钧嘶,內(nèi)部類為默認(rèn)訪問(wèn)權(quán)限(包訪問(wèn)權(quán)限)。我們可以在 Test
類中訪問(wèn) Human
的內(nèi)部類 Cup
琳疏,并使用該內(nèi)部類創(chuàng)建對(duì)象有决。注意我們創(chuàng)建時(shí)如何說(shuō)明類型以及使用 new
:
Human.Cup soloCup = me.new Cup();
我們?cè)趧?chuàng)建內(nèi)部類對(duì)象時(shí),必須基于一個(gè)外部類對(duì)象(me)空盼,并通過(guò)該外部類對(duì)象來(lái)創(chuàng)建 Cup
對(duì)象(me.new)书幕。
閉包
我們直接創(chuàng)建內(nèi)部類對(duì)象時(shí),必須是基于一個(gè)外部類對(duì)象我注。也就是說(shuō)按咒,內(nèi)部類對(duì)象必須依附于某個(gè)外部類對(duì)象。
與此同時(shí),內(nèi)部類對(duì)象可以訪問(wèn)它所依附的外部類對(duì)象的成員(即使是 private
的成員)励七。從另一個(gè)角度來(lái)說(shuō)智袭,內(nèi)部類對(duì)象附帶有創(chuàng)建時(shí)的環(huán)境信息,也就是其他語(yǔ)言中的 閉包(closure)特性掠抬。
class Human
{
private String name;
public Human(String n)
{
this.name = n;
}
public void changeName(String n)
{
this.name = n;
}
// 內(nèi)部類
class Cup
{
public String whosCup()
{
return name; // 通過(guò)內(nèi)部類對(duì)象訪問(wèn)外部類對(duì)象的 name 成員
}
}
}
public class Test
{
public static void main(String[] args)
{
Human me = new Human("Vamei");
Human him = new Human("Jerry");
Human.Cup myFirstCup = me.new Cup();
Human.Cup mySecondCup = me.new Cup();
Human.Cup hisCup = him.new Cup();
System.out.println(myFirstCup.whosCup());
System.out.println(mySecondCup.whosCup());
System.out.println(hisCup.whosCup());
}
}
輸出:
Vamei
Vamei
Jerry
在上面的例子中吼野,我們通過(guò)內(nèi)部類對(duì)象訪問(wèn)外部類對(duì)象的 name
成員。當(dāng)我們基于不同的外部對(duì)象創(chuàng)建內(nèi)部類對(duì)象時(shí)两波,所獲得的環(huán)境信息也將隨之變化瞳步。
嵌套 static 類
我們可以在類的內(nèi)部定義 static
類。這樣的類稱為 嵌套static類(nested static class)腰奋。
我們可以直接創(chuàng)建嵌套 static 類的對(duì)象单起,而不需要依附于外部類的某個(gè)對(duì)象。相應(yīng)的劣坊,嵌套 static 類也無(wú)法調(diào)用外部對(duì)象的方法嘀倒,也無(wú)法讀取或修改外部對(duì)象的數(shù)據(jù)。
從效果上看局冰,嵌套 static 類拓展了類的命名空間(name space)
class Human
{
// 嵌套static類
static class Chinese
{
public void Shout()
{
System.out.println("nihao");
}
}
}
public class Test
{
public static void main(String[] args)
{
Human.Chinese him = new Human.Chinese();
him.Shout();
}
}
輸出:
nihao