第六章 內部類
阿新 • • 發佈:2018-12-08
內部類
為什麼要使用內部類?
- 內部類可以訪問該類定義所在的作用域中的所有的資料,包括私有資料
- 內部類可以對同一個包的其他類隱藏起來
- 當要定義一個回撥函式並且不想編寫大量程式碼時,使用匿名內部類比較方便。
使用內部類訪問物件的狀態
內部類的物件總有一個隱式引用。它指向了建立它的外部類物件。
在一個內部類的物件被建立之時,它所在類的物件的引用被作為引數,傳遞給這個內部類的隱式建構函式。
內部類的特殊語法規則
- OuterClass.this 引用外部類的物件 eg
Talking.this.beep
ActionListener listenr =this.new TimePrinter();
在這裡,最新構造的actionListener物件的外圍類的引用被設定為建立內部類物件的方法中的this引用。- 在外圍類的作用域之外,
Outerclass.innerclass
可以這樣引用內部類 - 內部類中所有的靜態域必須是final
內部類是否有用,必要和安全?
與常規類相比,內部類訪問外圍類私有資料的特性更強大
內部實現?
- 編譯器會在外圍類中新增
static boolean access$0(TalkingClock)
區域性內部類
區域性內部類適用於內部類的物件只使用一次的情況。
- 區域性類不能用public 或 private修飾。
- 區域性類的優勢是,只在一個方法內定義,只被一個方法使用。其他類不知道該區域性類的存在。
由外部方法訪問變數 P252
與內部類相比較,區域性類的另一個優點是,可以訪問區域性變數。
區域性類的方法只可以引用定義為final的區域性變數。對於counter這種final不方便的情況,可以用長為1的陣列來儲存。
匿名內部類
匿名內部類的格式?
new SuperType(construction parameters)
{
inner class methods and data;
}
注意匿名類沒有類名。故沒有構造器。
如果有引數,作用是啥?引數傳遞給超類的構造器。(上面就是個例子)
但是,對於內部類實現介面的時候:不能有引數!
new InterfaceType()
{
inner class methods and data;
}
下面是用匿名內部類實現語音時鐘程式的原始碼:
/**
* A clock that prints the time in regular intervals.
*/
class TalkingClock
{
/**
* Starts the clock.
* @param interval the interval between messages (in milliseconds)
* @param beep true if the clock should beep
*/
public void start(int interval, boolean beep)
{
ActionListener listener = new ActionListener()//這是一個介面
{
public void actionPerformed(ActionEvent event)
{
System.out.println("At the tone, the time is " + new Date());
if (beep) Toolkit.getDefaultToolkit().beep();
}
};
Timer t = new Timer(interval, listener);
t.start();
}
}
但此處用lambda表示式會更加的簡潔。
小注釋:匿名陣列列表:
invite
(
new ArrayList<String>()
{
{
add("Harry");
add("Tony");
}
}
)
匿名子類在使用equals方法時要特別當心!
getClass()方法在使用時呼叫的是this.getClass(),但是靜態方法沒有內部類,這就不行了
怎麼辦?
new Object(){}.getClass.getEnclosingClass()
這樣就得到了包含這個靜態方法的類。可以算是匿名子類的一個應用吧。
靜態內部類
為什麼要靜態?
有時候不需要內部類引用外圍類的物件,所以宣告該內部類為static,取消產生引用。
靜態內部類的物件除了沒有對生成它的外圍類物件的引用特權外,與其他所有內部類完全一樣。
與常規內部類不同,靜態內部類可以有靜態域和方法。
下面是一個靜態內部類的例子:
class ArrayAlg
{
/**
* A pair of floating-point numbers
*/
public static class Pair
{
private double first;
private double second;
/**
* Constructs a pair from two floating-point numbers
* @param f the first number
* @param s the second number
*/
public Pair(double f, double s)
{
first = f;
second = s;
}
/**
* Returns the first number of the pair
* @return the first number
*/
public double getFirst()
{
return first;
}
/**
* Returns the second number of the pair
* @return the second number
*/
public double getSecond()
{
return second;
}
}
/**
* Computes both the minimum and the maximum of an array
* @param values an array of floating-point numbers
* @return a pair whose first element is the minimum and whose second element
* is the maximum
*/
public static Pair minmax(double[] values)
{
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
for (double v : values)
{
if (min > v) min = v;
if (max < v) max = v;
}
return new Pair(min, max);
}
}
下面是呼叫的方法:
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());
}
注意此處,內部類物件在靜態方法中構造,所以必須使用靜態內部類。