概念:
-
内部类也是一个语法糖,内部类指的就是在一个类的内部再定义一个类。
-
内部类之所以也是语法糖,是因为它仅仅是一个编译时的概念,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编程思想,在加上个人的一些观点与实践