【學習筆記】 唐大仕—Java程式設計 第5講 深入理解Java語言之5.5 內部類與匿名類
阿新 • • 發佈:2018-11-10
/**
* 內部類與匿名類
* @author cnRicky
* @date 2018.11.10
*/
內部類與匿名類
- 內部類(inner class)是在其他類中的類
- 匿名類(anonymous class)是一種特殊的內部類,它沒有類名
內部類(Inner class)
-
內部類的定義
- 將類的定義class xxxx{...}置入一個類的內部即可
- 編譯器生成xxxx$xxxx這樣的class檔案
- 內部類不能夠與外部類同名
-
內部類的使用
- 在封裝它的內的內部使用內部類,與普通的使用方式相同
- 在其他地方使用
- 類名前要冠以外部類的名字
- 在用new建立內部類時,也要在new前面冠以物件變數
- 外部物件名.new 內部類名(引數)
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.欄位及方法
-
例子:
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
}
}
}
內部類的修飾符
- 內部類與類中的欄位、方法一樣是外部類的成員,它的前面也可以有訪問控制符和其他修飾符
- 訪問控制符:public、protected,預設(default)及private
- 注:外部類只能夠使用public修飾或者預設
- final,abstract
- 訪問控制符:public、protected,預設(default)及private
static修飾符
-
用static修飾內部類,表名該內部類實際是一種外部類
- 因為它與外部類的例項無關
- 有人認為static的類是巢狀類(nested class),不是內部類(inner class)
-
static類在使用時:
- 1、例項化static類時,在new前面不需要用物件例項變數;
- 2、static類中不能訪問其外部類的非static的欄位及方法,即只能夠訪問static成員
- 3、static方法中不能訪問非static的域及方法,也不能夠不帶字首地new一個非static的內部類
-
例子:
public 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 = new 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
{
}
}
區域性類
- 在一個方法中也可以定義類,這種類稱為“方法中的內部類”
- 或者叫區域性類(local class)
- 例子:
class TestInnerInMethod
{
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;
class Inner{
public String toString(){
return("InnerSize:" + size +
// "localVar:" + localVar + //Error!
"finalLocalVar:" + finalLocalVar
);
}
}
return new Inner();
}
}
使用區域性類
-
1、同區域性變數一樣,方法中的內部類
- 不能夠用public,private,protected,static修飾
- 但可以被final或者abstract修飾
-
2、可以訪問其外部類的成員
-
3、不能夠訪問該方法的區域性變數,除非是final區域性變數
匿名類
-
匿名類(anonymous class)是一種特殊的內部類
- 它沒有類名,在定義類的同時就生成該物件的一個例項
- “一次性使用”的類
-
例子:
class TestInnerAnonymous
{
public static void main(String[] args)
{
}
}
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、不取名字,直接用其父類或介面的名字
- 也就是說,該類是父類的子類,或者實現了一個介面
- 編譯器生成xxxxx$之類的名字
-
2、類的定義的同時就建立例項,即類的定義前面有一個new
- new 類名或介面名(){ ...... }
- 不使用關鍵字class,也不使用extends及implements
-
3、在構造物件時使用父類構造方法
- 不能夠定義匿名類的構造方法,因為它沒有名字
- 如果new物件時,要帶引數,則使用父類的構造方法
匿名類的應用
- 用到介面的事件處理
- 註冊一個事件監聽器
- 示例AutoScore.java中
//SymAction ISymAction = new SymAction();
//btnNew.addActionListener(ISymAction);
btnNew.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent event)
{
......;
}
});
- 作為方法的引數
- 排序,給一個比較大小的介面
- 如:
Arrays.<Book>sort(books, new Comparator<Book>(){
public int compare(Book b1, Book b1){
return b1.getPrice()-b2.getPrice();
}
});