背景:這裏我們想要編寫一個名爲Bag的集合類,現有代碼如下
code:
public class MyBag<T> implements Iterable<T>{
public static class Node<T>{
T item;
Node<T> next;
}
Node<T> first = null;
int n = 0;
}
現在我們想要爲這個Bag添加一個迭代器。
step1:認識Iterable<T>接口
故名思意,實現這個接口的集合類是可迭代的,所以我們的Bag也需要實現。那麼這個接口需要重寫哪些方法?
只有一個方法,就是:
public Iterator<T> iterator() {
這個方法返回實現Iterator接口的類的實例化對象,這一點需要記住。自然我們需要定義一個類,來實現Iterator接口,或者直接使用匿名類。就是:
code(iterator()函數是使用匿名內部類的方法;後面的是使用內部類)
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private Node<T> n = null;
{
n=first;
}
@Override
public boolean hasNext() {
return n.next !=null;
}
@Override
public T next() {
if(hasNext()) {
Node<T> cur = n;
n = cur.next;
return cur.item;
}
else {
throw new NoSuchElementException();
}
}
};
}
public class ListIterator<T>implements Iterator<T>
{
private Node<T> n = null;
ListIterator(Node<T> _first){
n = _first;
}
@Override
public boolean hasNext() {
return n.next != null;
}
@Override
public T next() {
if(hasNext()) {
Node<T> cur = n;
n = cur.next;
return cur.item;
}
else {
throw new NoSuchElementException();
}
}
}
小插曲:上面的代碼展示匿名內部類的初始化方式。我們瞭解到,匿名內部類是沒有名字的,那他的構造函數怎麼搞?(上面的代碼已經有答案了)。
今天寫這個代碼的時候,一不小心寫成了這樣:
code(一不小心把Node<T> n = null;這個聲明語句寫到了外面,代碼如下)
@Override
public Iterator<T> iterator() {
Node<T> n = null;//這句話被我寫在了匿名類的外面
return new Iterator<T>() {
{
n=first;
}
@Override
public boolean hasNext() {
return n.next !=null;
}
@Override
public T next() {
if(hasNext()) {
Node<T> cur = n;
n = cur.next;
return cur.item;
}
else {
throw new NoSuchElementException();
}
}
};
}
這時編譯出錯:Local variable n defined in an enclosing scope must be final or effectively final
這句話的意思是,n應該被定義爲final,所以我在n的前面添加了final
這時編譯出錯:The final local variable n cannot be assigned, since it is defined in an enclosing type
這句話的意思是final變量不能被重新指派(這是當然)。
問題:
1、爲什麼在匿名內部類中給局部變量(函數中,但是在匿名類的外部)賦值,一定需要加final?
只是stack overflow中的一段話(中英對照):
【參考】問題連接,下面的圖是問題的評論
2、對於上面的第二個錯誤,有上面辦法解決?
【參考】這篇文章解決了問題二