Java內部類(成員內部類)
阿新 • • 發佈:2019-01-14
概念:
-
內部類也是一個語法糖,內部類指的就是在一個類的內部再定義一個類。
-
內部類之所以也是語法糖,是因為它僅僅是一個編譯時的概念,outer.java裡面定義了一個內部類inner,一旦編譯成功,就會生成兩個完全不同的.class檔案了,分別是outer.class和outer$inner.class。所以內部類的名字完全可以和它的外部類名字相同。
-
內部類分為四種:
1.成員內部類
2.區域性內部類
3.匿名內部類
4.靜態內部類(又稱巢狀類)
1.首先講成員內部類
- 在生成成員內部類物件時,此物件與製造它的外圍物件之間就有了一種聯絡,所以它能訪問外圍物件的所有成員,此外內部類還擁有其外部內的所有元素訪問權
- 例:
public interface Selector {
boolean end();
Object current();
void next();
}
public class Sequence { private Object [] items; private int next = 0; public Sequence(int size) { this.items = new Object[size]; } public void add(Object item){ if(next < items.length){ items[next++] = item; } } private class SequenceSelector implements Selector{ private int i = 0; @Override public boolean end() { return i == items.length; } @Override public Object current() { return items[i]; } @Override public void next() { if(i < items.length){ i++; } } } public Selector getSelector(){ return new SequenceSelector(); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) { sequence.add(Integer.toString(i)); } Selector selector = sequence.getSelector(); while (! selector.end()){ System.out.println(selector.current()); selector.next(); } }
-
為甚麼成員內部類能夠訪問外部內的所有元素,是因為 當某個外圍類
建立了成員內部時候,此物件必定會祕密的捕獲一個外部類的引用,然後成員內部類在訪問外圍類的成員時候,就是使用外圍內的引用來選擇外圍內的成員,編譯器會幫你處理所有的細節 -
下面是成員類部類通過反編譯工具的位元組碼檔案
// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov. // Jad home page: http://kpdus.tripod.com/jad.html // Decompiler options: packimports(3) fieldsfirst ansi space // Source File Name: Sequence.java package com.dongzhu.cn.prototype.test; import java.io.PrintStream; // Referenced classes of package com.dongzhu.cn.prototype.test: // Selector, Sequence private class Sequence$SequenceSelector implements Selector { private int i; final Sequence this$0; public boolean end() { System.out.println(Sequence.this); return i == Sequence.access$000(Sequence.this).length; } public Object current() { return Sequence.access$000(Sequence.this)[i]; } public void next() { if (i < Sequence.access$000(Sequence.this).length) i++; } private Sequence$SequenceSelector() { this$0 = Sequence.this; super(); i = 0; } } package com.dongzhu.cn.prototype.test; import java.io.PrintStream; public class Sequence { private Object[] items; private int next = 0; public Sequence(int size) { this.items = new Object[size]; } public void add(Object item) { if (this.next < this.items.length) { this.items[(this.next++)] = item; } } private class SequenceSelector implements Selector { private int i = 0; private SequenceSelector() {} public boolean end() { return this.i == Sequence.this.items.length; } public Object current() { return Sequence.this.items[this.i]; } public void next() { if (this.i < Sequence.this.items.length) { this.i += 1; } } } public Selector getSelector() { return new SequenceSelector(null); } public static void main(String[] args) { Sequence sequence = new Sequence(10); for (int i = 0; i < 10; i++) { sequence.add(Integer.toString(i)); } Selector selector = sequence.getSelector(); while (!selector.end()) { System.out.println(selector.current()); selector.next(); } } }
-
根據位元組碼檔案 可以清楚的看到內部類確實是通過某種方式拿到了外圍類的引用
-
拿到成員內部類引用的兩種方式
// 原始碼檔案在上面
Sequence sequence = new Sequence(10);
// 第一種通過.this 方式建立內部類物件
Selector selector = sequence.getSelector();
// 第二種通過.new 方式建立內部類物件
SequenceSelector sequenceSelector = sequence.new SequenceSelector();
總結:
本章主要講了內部類概念
內部類的分類
成員內部類的用法,及原理
宣告:本章節摘自與Java程式設計思想,在加上個人的一些觀點與實踐