一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 全面了解Java中的內(nèi)部類和匿名類

全面了解Java中的內(nèi)部類和匿名類

2020-05-29 14:44jingxian JAVA教程

下面小編就為大家?guī)硪黄媪私釰ava中的內(nèi)部類和匿名類。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

Java內(nèi)部類(Inner Class),類似的概念在C++里也有,那就是嵌套類(Nested Class),乍看上去內(nèi)部類似乎有些多余,它的用處對于初學(xué)者來說可能并不是那么顯著,但是隨著對它的深入了解,你會發(fā)現(xiàn)Java的設(shè)計者在內(nèi)部類身上的確是用心良苦。學(xué)會使用內(nèi)部類,是掌握J(rèn)ava高級編程的一部分,它可以讓你更優(yōu)雅地設(shè)計你的程序結(jié)構(gòu)。下面從以下幾個方面來介紹:

第一次見面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public interface Contents {
  int value();
}
 
public interface Destination {
  String readLabel();
}
 
public class Goods {
  private class Content implements Contents {
    private int i = 11;
    public int value() {
      return i;
    }
  }
 
  protected class GDestination implements Destination {
    private String label;
    private GDestination(String whereTo) {
      label = whereTo;
    }
    public String readLabel() {
      return label;
    }
  }
 
  public Destination dest(String s) {
    return new GDestination(s);
  }
  public Contents cont() {
    return new Content();
  }
}
 
class TestGoods {
  public static void main(String[] args) {
    Goods p = new Goods();
    Contents c = p.cont();
    Destination d = p.dest("Beijing");
  }
}

在這個例子里類Content和GDestination被定義在了類Goods內(nèi)部,并且分別有著protected和private修飾符來控制訪問級別。Content代表著Goods的內(nèi)容,而GDestination代表著Goods的目的地。它們分別實現(xiàn)了兩個接口Content和Destination。在后面的main方法里,直接用Contents c和Destination d進(jìn)行操作,你甚至連這兩個內(nèi)部類的名字都沒有看見!這樣,內(nèi)部類的第一個好處就體現(xiàn)出來了——隱藏你不想讓別人知道的操作,也即封裝性。

同時,我們也發(fā)現(xiàn)了在外部類作用范圍之外得到內(nèi)部類對象的第一個方法,那就是利用其外部類的方法創(chuàng)建并返回。上例中的cont()和dest()方法就是這么做的。那么還有沒有別的方法呢?當(dāng)然有,其語法格式如下:

?
1
2
3
outerObject=new outerClass(Constructor Parameters);
 
outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);

注意在創(chuàng)建非靜態(tài)內(nèi)部類對象時,一定要先創(chuàng)建起相應(yīng)的外部類對象。至于原因,也就引出了我們下一個話題——

非靜態(tài)內(nèi)部類對象有著指向其外部類對象的引用

對剛才的例子稍作修改:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Goods {
 
  private valueRate=2;
 
  private class Content implements Contents {
    private int i = 11*valueRate;
    public int value() {
      return i;
    }
  }
 
  protected class GDestination implements Destination {
    private String label;
    private GDestination(String whereTo) {
      label = whereTo;
    }
    public String readLabel() {
      return label;
    }
  }
 
  public Destination dest(String s) {
    return new GDestination(s);
  }
  public Contents cont() {
    return new Content();
  }
}

修改的部分用紅色顯示了。在這里我們給Goods類增加了一個private成員變量valueRate,意義是貨物的價值系數(shù),在內(nèi)部類Content的方法value()計算價值時把它乘上。我們發(fā)現(xiàn),value()可以訪問valueRate,這也是內(nèi)部類的第二個好處——一個內(nèi)部類對象可以訪問創(chuàng)建它的外部類對象的內(nèi)容,甚至包括私有變量!這是一個非常有用的特性,為我們在設(shè)計時提供了更多的思路和捷徑。要想實現(xiàn)這個功能,內(nèi)部類對象就必須有指向外部類對象的引用。 Java編譯器在創(chuàng)建內(nèi)部類對象時,隱式的把其外部類對象的引用也傳了進(jìn)去并一直保存著。這樣就使得內(nèi)部類對象始終可以訪問其外部類對象,同時這也是為什么在外部類作用范圍之外向要創(chuàng)建內(nèi)部類對象必須先創(chuàng)建其外部類對象的原因。

有人會問,如果內(nèi)部類里的一個成員變量與外部類的一個成員變量同名,也即外部類的同名成員變量被屏蔽了,怎么辦?沒事,Java里用如下格式表達(dá)外部類的引用:

?
1
outerClass.this

有了它,我們就不怕這種屏蔽的情況了。

靜態(tài)內(nèi)部類

和普通的類一樣,內(nèi)部類也可以有靜態(tài)的。不過和非靜態(tài)內(nèi)部類相比,區(qū)別就在于靜態(tài)內(nèi)部類沒有了指向外部的引用。這實際上和C++中的嵌套類很相像了,Java內(nèi)部類與C++嵌套類最大的不同就在于是否有指向外部的引用這一點上,當(dāng)然從設(shè)計的角度以及以它一些細(xì)節(jié)來講還有區(qū)別。

除此之外,在任何非靜態(tài)內(nèi)部類中,都不能有靜態(tài)數(shù)據(jù),靜態(tài)方法或者又一個靜態(tài)內(nèi)部類(內(nèi)部類的嵌套可以不止一層)。不過靜態(tài)內(nèi)部類中卻可以擁有這一切。這也算是兩者的第二個區(qū)別吧。

局部內(nèi)部類

是的,Java內(nèi)部類也可以是局部的,它可以定義在一個方法甚至一個代碼塊之內(nèi)。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Goods1 {
   public Destination dest(String s) {
     class GDestination implements Destination {
        private String label;
        private GDestination(String whereTo) {
          label = whereTo;
        }
        public String readLabel() { return label; }
     }
     return new GDestination(s);
   }
 
   public static void main(String[] args) {
     Goods1 g= new Goods1();
     Destination d = g.dest("Beijing");
   }
}

上面就是這樣一個例子。在方法dest中我們定義了一個內(nèi)部類,最后由這個方法返回這個內(nèi)部類的對象。如果我們在用一個內(nèi)部類的時候僅需要創(chuàng)建它的一個對象并創(chuàng)給外部,就可以這樣做。當(dāng)然,定義在方法中的內(nèi)部類可以使設(shè)計多樣化,用途絕不僅僅在這一點。

下面有一個更怪的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class Goods2{
   private void internalTracking(boolean b) {
     if(b) {
        class TrackingSlip {
          private String id;
          TrackingSlip(String s) {
             id = s;
          }
          String getSlip() { return id; }
        }
        TrackingSlip ts = new TrackingSlip("slip");
        String s = ts.getSlip();
     }
   }
 
   public void track() { internalTracking(true); }
 
   public static void main(String[] args) {
     Goods2 g= new Goods2();
     g.track();
   }
}

你不能在if之外創(chuàng)建這個內(nèi)部類的對象,因為這已經(jīng)超出了它的作用域。不過在編譯的時候,內(nèi)部類TrackingSlip和其他類一樣同時被編譯,只不過它由它自己的作用域,超出了這個范圍就無效,除此之外它和其他內(nèi)部類并沒有區(qū)別。

匿名內(nèi)部類

java的匿名內(nèi)部類的語法規(guī)則看上去有些古怪,不過如同匿名數(shù)組一樣,當(dāng)你只需要創(chuàng)建一個類的對象而且用不上它的名字時,使用內(nèi)部類可以使代碼看上去簡潔清楚。它的語法規(guī)則是這樣的:

?
1
new interfacename(){......}; 或 new superclassname(){......};

下面接著前面繼續(xù)舉例子:

?
1
2
3
4
5
6
7
8
9
10
public class Goods3 {
   public Contents cont(){
     return new Contents(){
        private int i = 11;
        public int value() {
          return i;
        }
     };
   }
}

這里方法cont()使用匿名內(nèi)部類直接返回了一個實現(xiàn)了接口Contents的類的對象,看上去的確十分簡潔。

在java的事件處理的匿名適配器中,匿名內(nèi)部類被大量的使用。例如在想關(guān)閉窗口時加上這樣一句代碼:

?
1
2
3
4
5
frame.addWindowListener(new WindowAdapter(){
   public void windowClosing(WindowEvent e){
     System.exit(0);
   }
});

有一點需要注意的是,匿名內(nèi)部類由于沒有名字,所以它沒有構(gòu)造函數(shù)(但是如果這個匿名內(nèi)部類繼承了一個只含有帶參數(shù)構(gòu)造函數(shù)的父類,創(chuàng)建它的時候必須帶上這些參數(shù),并在實現(xiàn)的過程中使用super關(guān)鍵字調(diào)用相應(yīng)的內(nèi)容)。如果你想要初始化它的成員變量,有下面幾種方法:

如果是在一個方法的匿名內(nèi)部類,可以利用這個方法傳進(jìn)你想要的參數(shù),不過記住,這些參數(shù)必須被聲明為final。

將匿名內(nèi)部類改造成有名字的局部內(nèi)部類,這樣它就可以擁有構(gòu)造函數(shù)了。

在這個匿名內(nèi)部類中使用初始化代碼塊。

為什么需要內(nèi)部類?

java內(nèi)部類有什么好處?為什么需要內(nèi)部類?

首先舉一個簡單的例子,如果你想實現(xiàn)一個接口,但是這個接口中的一個方法和你構(gòu)想的這個類中的一個方法的名稱,參數(shù)相同,你應(yīng)該怎么辦?這時候,你可以建一個內(nèi)部類實現(xiàn)這個接口。由于內(nèi)部類對外部類的所有內(nèi)容都是可訪問的,所以這樣做可以完成所有你直接實現(xiàn)這個接口的功能。

不過你可能要質(zhì)疑,更改一下方法的不就行了嗎?

的確,以此作為設(shè)計內(nèi)部類的理由,實在沒有說服力。

真正的原因是這樣的,java中的內(nèi)部類和接口加在一起,可以的解決常被C++程序員抱怨java中存在的一個問題——沒有多繼承。實際上,C++的多繼承設(shè)計起來很復(fù)雜,而java通過內(nèi)部類加上接口,可以很好的實現(xiàn)多繼承的效果。

java內(nèi)部類總結(jié)

(1)  在方法間定義的非靜態(tài)內(nèi)部類:

● 外圍類和內(nèi)部類可互相訪問自己的私有成員。

● 內(nèi)部類中不能定義靜態(tài)成員變量。

在外部類作用范圍之外向要創(chuàng)建內(nèi)部類對象必須先創(chuàng)建其外部類對象

(2) 在方法間定義的靜態(tài)內(nèi)部類:

● 只能訪問外部類的靜態(tài)成員。

靜態(tài)內(nèi)部類沒有了指向外部的引用

(3) 在方法中定義的局部內(nèi)部類:

● 該內(nèi)部類沒有任何的訪問控制權(quán)限

● 外圍類看不見方法中的局部內(nèi)部類的,但是局部內(nèi)部類可以訪問外圍類的任何成員。

● 方法體中可以訪問局部內(nèi)部類,但是訪問語句必須在定義局部內(nèi)部類之后。

● 局部內(nèi)部類只能訪問方法體中的常量,即用final修飾的成員。

(4) 在方法中定義的匿名內(nèi)部類:

● 沒有構(gòu)造器,取而代之的是將構(gòu)造器參數(shù)傳遞給超類構(gòu)造器

當(dāng)你只需要創(chuàng)建一個類的對象而且用不上它的名字時,使用匿名內(nèi)部類可以使代碼看上去簡潔清楚。

以上這篇全面了解Java中的內(nèi)部類和匿名類就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持服務(wù)器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品嫩草影院一二三区入口 | 经典千人斩一区二区视频 | 亚洲精品国产在线网站 | 国语视频高清在线观看 | 四虎私人影院 | 亚洲精品精品一区 | 男人肌肌捅女人 | 免费看美女被靠到爽的视频 | 国产精品2 | 性bbbb妇女激情 | 久久99精品久久久久久园产越南 | 好女孩韩剧免费观看 | 韩国男女做性全过程视频 | 成人在线第一页 | 免费高清视频免费观看 | 男同激情视频 | 91国在线观看| 欧美日韩在线观看精品 | 糖心在线观看网 | 99九九精品视频 | 美女露鸡鸡 | 好大好硬好深好爽想要之黄蓉 | 亚洲国产综合久久精品 | 男生操女生的漫画 | 毛片网在线观看 | 天堂精品高清1区2区3区 | 美女的让男人桶爽30分钟的 | 日韩欧美综合在线二区三区 | 国产经典一区 | 国模李丽莎大尺度啪啪 | 国产午夜精品一区二区三区 | 亚洲色图影院 | 草草精品视频 | 高h细节肉爽文办公室 | juy799大岛优香在线观看 | 日韩一区二区三区四区五区 | 免费在线公开视频 | 喜欢老头吃我奶躁我的动图 | 国产精品美女久久久久网站 | 色综合网亚洲精品久久 | www.亚洲视频.com |