パラメーターを渡すこと、または匿名パラメーターに外部パラメーターにアクセスすることは可能ですか?例えば:
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
}
});
実際の名前付きクラスとしてリスナーを作成せずに、リスナーがmyVariableにアクセスする方法、またはmyVariableを渡す方法はありますか?
技術的には、匿名クラスにはコンストラクターがないためです。
ただし、クラスは包含スコープから変数を参照できます。匿名クラスの場合、これらは包含クラスからのインスタンス変数またはfinalとマークされたローカル変数になります。
編集:Peterが指摘したように、匿名クラスのスーパークラスのコンストラクターにパラメーターを渡すこともできます。
はい、「this」を返す初期化メソッドを追加し、すぐにそのメソッドを呼び出します。
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
private int anonVar;
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
// It's now here:
System.out.println("Initialized with value: " + anonVar);
}
private ActionListener init(int var){
anonVar = var;
return this;
}
}.init(myVariable) );
「最終」宣言は必要ありません。
はい。内部クラスから見える変数をキャプチャできます。唯一の制限は、finalでなければならないことです
このような:
final int myVariable = 1;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Now you can access it alright.
}
});
これは魔法を行います
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
int myVariable;
public void actionPerformed(ActionEvent e) {
// myVariable ...
}
public ActionListener setParams(int myVariable) {
this.myVariable = myVariable;
return this;
}
}.setParams(myVariable));
http://www.coderanch.com/t/567294/Java/java/declare-constructor-anonymous-class に示すように、インスタンス初期化子を追加できます。これは名前を持たず、最初に実行されるブロックです(コンストラクターと同じように)。
なぜJavaインスタンス初期化子? および インスタンス化子とコンストラクターの違いは? でも議論されているようです。コンストラクターとの違いについて説明しています。
私の解決策は、実装された匿名クラスを返すメソッドを使用することです。通常の引数をメソッドに渡すことができ、匿名クラス内で使用できます。
例:(テキストボックスの変更を処理するGWTコードから):
/* Regular method. Returns the required interface/abstract/class
Arguments are defined as final */
private ChangeHandler newNameChangeHandler(final String axisId, final Logger logger) {
// Return a new anonymous class
return new ChangeHandler() {
public void onChange(ChangeEvent event) {
// Access method scope variables
logger.fine(axisId)
}
};
}
この例では、新しい匿名クラスメソッドは次のように参照されます。
textBox.addChangeHandler(newNameChangeHandler(myAxisName, myLogger))
または、OPの要件を使用:
private ActionListener newActionListener(final int aVariable) {
return new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Your variable is: " + aVariable);
}
};
}
...
int myVariable = 1;
newActionListener(myVariable);
他の人々はすでに、匿名クラスはfinal変数のみにアクセスできると答えています。しかし、元の変数を非ファイナルに保つ方法についての質問は未解決のままです。 Adam Mlodzinski は解決策を示しましたが、かなり肥大化しています。この問題には、はるかに簡単な解決策があります。
myVariable
を最終的にしたくない場合は、それが最終的なものである場合、それが問題にならない新しいスコープでラップする必要があります。
int myVariable = 1;
{
final int anonVar = myVariable;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
// Use anonVar instead of myVariable
}
});
}
Adam Mlodzinskiは彼の答えでは他に何もしませんが、より多くのコードを使用します。
plain lambdas (「ラムダ式は変数をキャプチャできる」)を使用できます
int myVariable = 1;
ActionListener al = ae->System.out.println(myVariable);
myButton.addActionListener( al );
または関数
Function<Integer,ActionListener> printInt =
intvar -> ae -> System.out.println(intvar);
int myVariable = 1;
myButton.addActionListener( printInt.apply(myVariable) );
関数の使用は、デコレータとアダプタをリファクタリングするのに最適な方法です こちらを参照
ラムダについて学習し始めたばかりなので、間違いを見つけたら、気軽にコメントを書いてください。
外部変数に値を入力する簡単な方法(anonymusクラスに属さない)は、どれだけ小さいかです!
同じ方法で、外部変数の値を取得したい場合、必要なものを返すメソッドを作成できます!
public class Example{
private TypeParameter parameter;
private void setMethod(TypeParameter parameter){
this.parameter = parameter;
}
//...
//into the anonymus class
new AnonymusClass(){
final TypeParameter parameterFinal = something;
//you can call setMethod(TypeParameter parameter) here and pass the
//parameterFinal
setMethod(parameterFinal);
//now the variable out the class anonymus has the value of
//of parameterFinal
});
}