[英]How to pass parameters to anonymous class?
是否可以向匿名類傳遞參數或訪問外部參數? 例如:
int myVariable = 1;
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// How would one access myVariable here?
}
});
有沒有辦法讓偵聽器訪問 myVariable 或傳遞 myVariable 而不將偵聽器創建為實際的命名類?
是的,通過添加一個返回'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的局部變量。
編輯 :正如Peter所指出的,您還可以將參數傳遞給匿名類的超類的構造函數。
是。 你可以捕獲變量,對內部類可見。 唯一的限制是它必須是最終的
像這樣:
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);
其他人已經回答說匿名類只能訪問最終變量。 但他們留下了如何保持原始變量非最終的問題。 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在他的回答中沒有做任何其他事情,但有更多的代碼。
你可以使用普通的lambdas (“lambda表達式可以捕獲變量”)
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) );
使用Function是重構裝飾器和適配器的好方法, 請參見此處
我剛開始學習lambdas,所以如果發現錯誤,請隨意寫評論。
將一些值放入外部變量(不屬於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
});
}
你可以使用一個合格的:
public class Foo {
int myVariable = 1;
new ActionListener() {
public void actionPerformed(ActionEvent e) {
Foo.this.myVariable = 8;
}
});
}
我認為匿名類基本上就像lambdas但語法更差......結果證明這是真的,但語法更糟,導致(應該是)本地變量滲透到包含類中。
您可以通過將它們放入父類的字段來訪問任何最終變量。
例如
接口:
public interface TextProcessor
{
public String Process(String text);
}
類:
private String _key;
public String toJson()
{
TextProcessor textProcessor = new TextProcessor() {
@Override
public String Process(String text)
{
return _key + ":" + text;
}
};
JSONTypeProcessor typeProcessor = new JSONTypeProcessor(textProcessor);
foreach(String key : keys)
{
_key = key;
typeProcessor.doStuffThatUsesLambda();
}
我不知道他們是否已經在java 8中對此進行了排序(我已經陷入了EE世界而且還沒有得到8)但是在C#中它看起來像這樣:
public string ToJson()
{
string key = null;
var typeProcessor = new JSONTypeProcessor(text => key + ":" + text);
foreach (var theKey in keys)
{
key = theKey;
typeProcessor.doStuffThatUsesLambda();
}
}
在c#中你不需要一個單獨的界面......我想念它! 我發現自己在java中做了更糟糕的設計,並重復自己更多,因為你需要在java中添加的代碼量+復雜性來重用某些東西比復制和粘貼很多時候更糟糕。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.