定義
定義在一個(gè)類里面的類就叫內(nèi)部類。
作用
1、內(nèi)部類可以很好的隱藏實(shí)現(xiàn);
一般的非內(nèi)部類,是不允許有 private 與protected權(quán)限的,但內(nèi)部類可以
2、內(nèi)部類可以實(shí)現(xiàn)多重繼承;
3、內(nèi)部類擁有外部類的所有訪問(wèn)權(quán)限;
4、可以避免父類和接口同方法名時(shí)的覆蓋問(wèn)題。
解析
1、內(nèi)部類可以很好的隱藏實(shí)現(xiàn);
由于外部類是不允許定義為private或者protected類型的,所以如果我們要隱藏一些我們實(shí)現(xiàn)細(xì)節(jié),就可以通過(guò)內(nèi)部類來(lái)實(shí)現(xiàn),比如支付是比較核心的功能,需要盡可能的隱藏其實(shí)現(xiàn)細(xì)節(jié),調(diào)用者只需要能夠使用即可,如下:
public interface IPay{
void pay();
}
public class Payer1 {
private class PayImpl implements IPay{
public void pay() {
System.out.println("pay ing...");
}
}
public IPay startPay() {
return new PayImpl();
}
}
class TestPay {
public static void main(String[] args) {
Payer1 pm = new Payer1();
IPay p = pm.startPay();
p.pay();
}
}
上面的PayImpl定義在內(nèi)部類中,用private修飾符來(lái)控制訪問(wèn)權(quán)限。在后面的main方法中,直接通過(guò)IPay.pay()方法進(jìn)行操作,外部調(diào)用者甚至連該實(shí)現(xiàn)類的名字都沒(méi)有看見(jiàn),這樣就可以盡可能的隱藏實(shí)現(xiàn)細(xì)節(jié),體現(xiàn)java的封裝性。
2、內(nèi)部類可以實(shí)現(xiàn)多重繼承;
現(xiàn)實(shí)世界中是存在多重繼承關(guān)系的,比如,孩子既繼承父親也繼承母親的基因,父親會(huì)work,母親會(huì)dancing,孩子繼承了父母的所有這些基因。在java代碼中該如何表示呢?由于在java中一個(gè)類只支持單繼承,多實(shí)現(xiàn),但是對(duì)于這種場(chǎng)景,用接口來(lái)定義父親和母親似乎不太合理,所以這時(shí)候內(nèi)部類就發(fā)揮其作用了:
public class father {
void work(){...}
}
public class mother{
void dancing(){...}
}
public class Child {
public static void main(String args[])
{
Child child=new Child ();
child.work();
child.dancing();
}
public void work(){
InnerChild1 child1 = new InnerChild1 ();
child1.work();
}
public void dancing(){
InnerChild2 child2 = new InnerChild2 ();
child2.dancing();
}
private class InnerChild1 extends father{
void work() {
super.work();
}
}
private class InnerChild2 extends mother{
void dancing() {
super.dancing();
}
}
}
這樣孩子便繼承了父母的優(yōu)秀基因,可謂才藝雙馨。
3、內(nèi)部類擁有外部類的所有訪問(wèn)權(quán)限
由于非靜態(tài)內(nèi)部類會(huì)持有外部類的引用,因此,非靜態(tài)內(nèi)部類可以訪問(wèn)外部類的所有屬性及方法,這樣可以為程序的設(shè)計(jì)帶來(lái)極大的靈活性。對(duì)第一段代碼稍作修改:
public interface IPay{
void pay();
}
public class Payer1 {
private double money;
private class PayImpl implements IPay{
public void pay() {
money --;
System.out.println("pay ing...");
}
}
public IPay startPay() {
return new PayImpl();
}
}
class TestPay {
public static void main(String[] args) {
Payer1 pm = new Payer1 ();
IPay p = pm.startPay();
p.pay();
}
}
我們?cè)谕獠款愔行略隽艘粋€(gè)用private修飾的money字段,然后在內(nèi)部類PayImpl 調(diào)用pay方法時(shí),修改了該字段的值,這樣可以直接通過(guò)內(nèi)部類來(lái)訪問(wèn)外部類。
4、可以避免父類和接口同方法名時(shí)的覆蓋問(wèn)題
試想一下,如果你的類要繼承一個(gè)類,還要實(shí)現(xiàn)一個(gè)接口,可是你發(fā)覺(jué)你繼承的類和接口里面有兩個(gè)同名的方法該怎么辦?你怎么區(qū)分它們?你可能會(huì)說(shuō),我改成不同名的不就完事了嗎,多大點(diǎn)事?如果這個(gè)父類和接口你都能改的話,確實(shí)可以這樣做,但是有沒(méi)有辦法在不改的前提下解決這個(gè)問(wèn)題呢,或者說(shuō)你根本就沒(méi)有機(jī)會(huì)改,比如,他們是你引入的第三方SDK呢,你該咋辦? 這時(shí)候就需要我們實(shí)現(xiàn)內(nèi)部類了:
public class Payer{
void pay(){
System.out.println("Payer implement...");
}
}
public interface IPay{
void pay();
}
//上面部分中Payer類和IPay接口有相同的方法pay(),然后我們有如下實(shí)現(xiàn)方法:
public class Payer1 extends Payer implements IPay{
@override
public void pay() {
System.out.println("pay ing...");
}
}
// 想問(wèn)一下大家pay()這個(gè)方法是屬于覆蓋Payer這里的方法呢?還是IPay這里的方法。我怎么能調(diào)到Payer這里的方法?顯然這是不好區(qū)分的。而我們?nèi)绻脙?nèi)部類就很好解決這一問(wèn)題了??聪旅娲a
public class Payer1 extends Payer {
private class InnerPayer implements IPay {
public void pay() {
Payer1.this.pay();
}
}
IPay startPay() {
return new InnerPayer ();
}
}
class TestPay {
public static void main(String[] args) {
Payer1 pm = new Payer1 ();
IPay p = pm.startPay();
p.pay();
}
}
這樣就完美的解決了同名方法覆蓋的問(wèn)題。