1. 程式人生 > >Java筆記丨20 內部類與匿名類

Java筆記丨20 內部類與匿名類

內部類是在其他類中的類

匿名類是一種特殊的內部類,它沒有類名

 

內部類

內部類的定義

將類的定義class xxxx{…}置入一個類的內部即可

編譯器生成xxxx$xxxx這樣的class檔案

內部類不能與外部類同名

內部類的使用

在封裝它的類的內部使用內部類,與普通類的使用方式相同

在其他地方使用,類名前要冠以外部類的名字。在用new建立內部類時,也要在new前面冠以物件變數:外部物件名.new內部類名(引數)

示例:TestInnerClass.java

class TestInnerClass{

       public static void main( String[] args ){

              Parcel p = new Parcel();

              p.testShip();



              Parcel.Contents c = p.new Contents(33);

              Parcel.Destination d = p.new Destination( "Hawii" );

              p.setProperty( c, d );

              p.ship();

       }

}



class Parcel {

  private Contents c;

  private Destination d;

  class Contents {

    private int i;

       Contents( int i ){ this.i = i; }

    int value() { return i; }

  }

  class Destination {

    private String label;

    Destination(String whereTo) {label = whereTo;}

    String readLabel() { return label; }

  }

  void setProperty( Contents c, Destination d ){

       this.c =c; this.d = d;

  }

  void ship(){

       System.out.println( "move "+ c.value() +" to "+ d.readLabel() );

  }

  public void testShip() {

    c = new Contents(22);

    d = new Destination("Beijing");

    ship();

  }

}

 

在內部類中使用外部類的成員

內部類可以直接訪問外部類的欄位及方法(即使private也可以)

如果內部類有與外部類同名的欄位或方法,可以用:外部類名.this.欄位及方法

示例:TestInnerThis.java

public class TestInnerThis

{   

       public static void main(String args[]){

           A a = new A();

           A.B b = a.new B();

           b.mb(333);

    }

}



class A

{

       private int s = 111;



       public class B {

           private int s = 222;

           public void mb(int s) {

               System.out.println(s);// 區域性變數s

               System.out.println(this.s); // 內部類物件的屬性s

               System.out.println(A.this.s); //  外層類物件屬性s

           }

    }

}

結果:

333

222

111

 

內部類的修飾符

內部類與類中的欄位、方法一樣是外部類的成員,它前面也可以有訪問控制符和其他修飾符

訪問控制符:public protected 預設及private

注:外部類只能夠用public修飾或者預設

final abstract

 

static修飾符

用static修飾內部類,表明該內部類實際是一種外部類,因為它與外部類例項無關。有人認為static是巢狀類,不是內部類。

static類在使用時:

1.例項化static類時,在new前面不需要用物件例項變數

2.static類中不能

訪問其外部類的非static的欄位及方法,即只能訪問static成員

3.static方法中不能訪問非static的域及方法,也不能不帶字首地new一個非static內部類

示例:TetsInnerStatic.java

class TestInnerStatic

{

       public static void main(String[] args)

       {

              A.B a_b = new A().new B();  // ok

              A a = new A();

              A.B ab =  a.new B();



              Outer.Inner oi = new Outer.Inner();

              //Outer.Inner oi2 = Outer.new Inner();  //!!!error  

              //Outer.Inner oi3 = new Outer().new Inner(); //!!! error

       }

}



class A   

{

       private int x;

       void m(){

              new B();

       }

       static void sm(){

              //new B();  // error!!!!

       }

       class B

       {

              B(){ x=5; }

       }

}



class Outer  

{

       static class Inner

       {

       }

}

區域性類

在一個方法中也可以定義類,這種類稱為“方法中的內部類”或區域性類

使用區域性類

1.同區域性變數一樣,方法中的內部類

不能夠用public、private、protected、static修飾,但可以用final或abstract修飾

2.可以訪問其外部類的成員

3.不能夠訪問該方法的區域性變數,除非是final區域性變數

 

匿名類

匿名類是一種特殊的內部類。它沒有類名,在定義類的同時就生成該物件的一個例項。一次性使用的類

class TestInnerAnonymous

{

       public static void main(String[] args)

       {

              Object obj = new Outer().makeTheInner(47);

              System.out.println("Hello World!" + obj.toString() );

       }

}



class Outer

{

       private int size = 5;

       public Object makeTheInner( int localVar )

       {

              final int finalLocalVar = 99;

              return new Object()  {

                     public String toString() {

                            return ( " InnerSize: " + size +

                                   " finalLocalVar: " + finalLocalVar

                            );

                     }

              };

       }

}

匿名類的使用

1.不取名字,直接用其父類或介面的名字

也就是說,該類是父類的子類,或者實現了一個介面

編譯器生成xxxx$1之類的名字

2.類的定義同時就建立例項,即類的定義前面有一個new

new類名或介面名(){…}

不使用關鍵字class,也不使用extends及implements

3.在構造物件時使用父類的構造方法

不能夠定義構造方法,因為它沒有名字

如果new物件時,要帶引數,則使用父類的構造方法

 

匿名類的應用

作為方法的引數

排序,給一個比較大小的介面

如:SortTest.java

import java.util.Arrays;

import java.util.Comparator;



class SortTest {

       public static void main(String[] args){

      

              Book[] books = new Book[10];

              for (int i=0; i<books.length; i++ ){

                     books[i] = new Book((int)(Math.random()*100));

              }

              dump(books);

              Arrays.<Book>sort( books, new Comparator<Book>(){

                     public int compare(Book b1, Book b2){

                            return b1.getPrice()-b2.getPrice();

                     }

              });

              dump(books);

       }

       static void dump( Book [] books ){

              for (int i=0; i<books.length; i++ ){

                     System.out.print(books[i]+" ");

              }

              System.out.println();

       }

}

class Book

{

       private int price;

       Book(int price){ this.price=price; }

       int getPrice(){ return price;}

       public String toString(){ return ""+price; }

}