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類中不能
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; }
}