1. 程式人生 > >Java內部類(成員內部類)

Java內部類(成員內部類)

概念:

  • 內部類也是一個語法糖,內部類指的就是在一個類的內部再定義一個類。

  • 內部類之所以也是語法糖,是因為它僅僅是一個編譯時的概念,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程式設計思想,在加上個人的一些觀點與實踐