考慮下面的例子
class InnerSuper{
void mInner(){}
}
class Outer{
int aOuter=10;
InnerSuper mOuter(){
int aLocal=3999;
class Inner extends InnerSuper{
int aInner=20;
void mInner(){
System.out.println("a Inner : "+aInner);
System.out.println("a local : "+aLocal);
}
}
Inner iob=new Inner();
return iob;
}
}
class Demo{
public static void main(String args[]){
Outer ob=new Outer();
InnerSuper iob=ob.mOuter();
iob.mInner();
}
}
這不會生成Java 1.8或以上的任何錯誤。但在以前的版本中,這會生成一個錯誤,要求您明確聲明在內部類中訪問的本地變量爲final。 因爲編譯器會做的是保留由內部類訪問的本地變量的副本,以便即使方法/塊結束並且局部變量超出作用域,副本也將存在。它要求我們聲明final,因爲如果變量在程序後面動態更改其值後在本地內部類或聲明瞭匿名類,則由編譯器創建的副本不會更改爲其新值並且可能通過不產生預期產出而導致內部階層出現問題。因此它建議我們明確宣佈它是最終的。
但在Java 1.8,因爲編譯器聲明訪問的本地變量隱含最終也不會產生錯誤。 它在Java文檔
匿名類遵循未聲明爲final或者有效最終其封閉 範圍無法訪問局部變量陳述。
讓我來解釋一下有效的final。考慮以上程序
class Outer{
int aOuter=10;
InnerSuper mOuter(){
int aLocal=3999;
class Inner extends InnerSuper{
int aInner=20;
void mInner(){
System.out.println("a Inner : "+aInner);
System.out.println("a local : "+aLocal);
}
}
aLocal=4000;
Inner iob=new Inner();
return iob;
}
}
即使在Java中1.8,這將產生一個錯誤的以下修改過的版本。這是因爲aLocal是在程序中動態分配的。這意味着變量不能被編譯器認爲是有效的最終。從我所瞭解的情況來看,編譯器聲明瞭最終沒有動態改變的變量。這被稱爲變量是有效的最終。
因此,建議您聲明本地內部類或匿名類顯式最終訪問的局部變量以避免任何錯誤。
'如果我們嘗試訪問匿名類中的非最終實例變量,同樣的原因可能適用於這種情況。「....這就是所謂的訪問對象的字段,從其引用。爲什麼對象的起源或其類的聲明很重要? –
@ user2499800:你見過我的回答嗎?你在哪裏與此達成?如果您回覆,請稍等... :) –