Java 內部類

要用到內部類:

在java開發學習中我們經常會碰到內部類。定義:內部類是定義在一個類中的類。

優點:

  1. 內部類方法可以訪問該類定義所在的作用域中的數據。
  2. 內部類對同一個包中的其他類隱藏起來。
  3. 想要定義一個回調函數時,使用匿名內部類 比較便捷。

內部類又有很多的優勢:首先舉一個簡單的例子,如果你想實現一個接口,但是這個接口中的一個方法和你構想的這個類中的一個方法名稱參數相同,你應該怎麼辦?這時候,你可以建一個內部類實現這個接口。由於內部類對外部類的所有內容都是可訪問的,所以這樣做可以完成所有你直接實現這個接口的功能。不過你可能要質疑,更改一下方法的不就行了嗎?的確,以此作爲設計內部類的理由,實在沒有說服力。

真正的原因是這樣的,java中的內部類和接口加在一起,從而java 通過內部類加上接口,可以很好的實現多繼承的效果。
 

內部類的分類和使用

1、成員內部類: 即作爲外部類的一個成員存在,與外部類的屬性、方法並列。注意:成員內部類中不能定義靜態變量,但可以訪問外部類的所有成員。

值得注意的是成員內部類編譯成功後會生成的兩個不同的類(.class)

成員內部類的優點:

  1. 內部類作爲外部類的成員,可以訪問外部類的私有成員或屬性。(即使將外部類聲明爲PRIVATE,但是對於處於其內部的內部類還是可見的。)
  2. 用內部類定義在外部類中不可訪問的屬性。這樣就在外部類中實現了比外部類的private還要小的訪問權限。
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;

public class InnerClassTest
{
    public static void main(String[] args)
    {
        TalkingClock clock = new TalkingClock(1000, true);
        clock.start();

        // keep program running until user selects "Ok"
        JOptionPane.showMessageDialog(null, "Quit program?");
        System.exit(0);
    }
}

/**
 * A clock that prints the time in regular intervals.
 */
class TalkingClock
{
    private int interval;
    private boolean beep;

    /**
     * Constructs a talking clock
     * @param interval the interval between messages (in milliseconds)
     * @param beep true if the clock should beep
     */
    public TalkingClock(int interval, boolean beep)
    {
        this.interval = interval;
        this.beep = beep;
    }

    /**
     * Starts the clock.
     */
    public void start()
    {
        ActionListener listener = new TimePrinter();
        Timer t = new Timer(interval, listener);
        t.start();
    }

    public class TimePrinter implements ActionListener
    {
        public void actionPerformed(ActionEvent event)
        {
            Date now = new Date();
            System.out.println("At the tone, the time is " + now);
            if (beep) Toolkit.getDefaultToolkit().beep();
        }
    }
}

 

2、局部內部類: 即在方法中定義的內部類,與局部變量類似,在局部內部類前不加修飾符public或private,其範圍爲定義它的代碼塊。

優點:對外部世界可以完全隱藏起來!只有start方法知道它的存在。

上面的例子中,TimePrinter這個類只在start中用了一次。這種情況,我們可以定義局部類。

    public void start()
    {
	     class TimePrinter implements ActionListener
	    {
		        public void actionPerformed(ActionEvent event)
		        {
		            Date now = new Date();
		            System.out.println("At the tone, the time is " + now);
		            if (beep) Toolkit.getDefaultToolkit().beep();
		        }
	    }
	     ActionListener listener = new TimePrinter();
	     Timer t = new Timer(interval, listener);
	     t.start();
    }

 

3、靜態內部類: 有時只是爲了把一個類隱藏在另外一個類的內部,並不需要內部類引用外圍類的對象。此時,聲明爲static ,以便取消產生的引用。注意:靜態內部類中可以定義靜態或者非靜態的成員

public class StaticInnerClassTest
{
    public static void main(String[] args)
    {
        double[] d = new double[20];
        for (int i = 0; i < d.length; i++)
            d[i] = 100 * Math.random();
        ArrayAlg.Pair p = ArrayAlg.minmax(d);
        System.out.println("min = " + p.getFirst());
        System.out.println("max = " + p.getSecond());
    }
}

class ArrayAlg
{
    public static class Pair
    {
        private double first;
        private double second;
        
        public Pair(double f, double s)
        {
            first = f;
            second = s;
        }

        public double getFirst()
        {
            return first;
        }
        
        public double getSecond()
        {
            return second;
        }
    }

    public static Pair minmax(double[] values)
    {
        double min = Double.MAX_VALUE;
        double max = Double.MIN_VALUE;
        for (double v : values)
        {
            if (min > v) min = v;
            if (max < v) max = v;
        }
        return new Pair(min, max);
    }
}

 

4、匿名內部類: 匿名內部類是在抽象類和接口的基礎之上發展起來的。

匿名內部類如果繼承自接口,必須實現指定接口的方法,且無參數 。匿名內部類如果繼承自類,參數必須按父類的構造函數的參數傳遞

匿名內部類的特點:

  1. 一個類用於繼承其他類或是實現接口,並不需要增加額外的方法,只是對繼承方法的事先或是覆蓋。
  2. 只是爲了獲得一個對象實例,不需要知道其實際類型。
  3. 類名沒有意義,也就是不需要使用到。
 

匿名類與內部的聯繫與區別:

按所在位置可以分爲兩大類:
1、在類的方法中
特點:
a、可以訪問宿主類的所有元素 ;
b、保存宿主類對象的引用,創建對象時必須有宿主類對象;
c、 不能有靜態數據;
繼續劃分:
A、本地內部類;
B、匿名內部類
兩者的區別在於本地內部類有構造方法,而匿名內部類只能實例初始化;
2、在類或接口作用域中;
A、普通內部類
B、靜態內部類

內部類總結:
1.內部類作爲外部類的一個特殊的成員來看待,因此它有類成員的封閉等級:private ,protected,默認(friendly),public 它有類成員的修飾符: static,final,abstract
2.非靜態內部類nested inner class,內部類隱含有一個外部類的指針this,因此,它可以訪問外部類的一切資源(當然包括private)外部類訪問內部類的成員,先要取得內部類的對象,並且取決於內部類成員的封裝等級。非靜態內部類不能包含任何static成員.
3.靜態內部類:static inner class,不再包含外部類的this指針,並且在外部類裝載時初始化. 靜態內部類只能訪問外部類static成員. 外部類訪問靜態內部類的成員:static成員:類名.成員;非static成員:對象.成員
4.對於方法中的內部類或塊中內部類只能訪問塊中或方法中的final變量。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章