如何将parameter passing给匿名类?
是否有可能传递参数,或访问外部参数到一个匿名类? 例如:
int myVariable = 1; myButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { // How would one access myVariable here? } });
是否有任何方法让侦听器访问myVariable或传递myVariable而不创build侦听器作为实际的命名类?
从技术上讲,不,因为匿名类不能有构造函数。
但是,类可以引用来自包含范围的variables。 对于匿名类,这些可以是来自包含类(es)的实例variables,也可以是标记为最终的局部variables。
编辑 :正如Peter指出的那样,您也可以将parameter passing给匿名类的超类的构造函数。
是的,通过添加返回“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) );
不需要“最终”声明。
是。 你可以捕捉内部类可见的variables。 唯一的限制是它必须是最终的
喜欢这个:
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实例初始值设定项被讨论? 和一个实例初始值设定项与构造函数有什么不同? 讨论与构造函数的差异。
我的解决scheme是使用返回实现的匿名类的方法。 常规参数可以传递给方法,并且可以在匿名类中使用。
例如:(从一些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);
其他人已经回答说,匿名类只能访问最终variables。 但他们留下的问题是如何保持原始variables不是最终的。 亚当Mlodzinski给了一个解决scheme,但是非常臃肿。 这个问题有一个更简单的解决scheme:
如果你不希望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在他的回答中没有做任何其他的事情,但是代码更多。
将一些值放入外部variables(不属于anonymus类)的一个简单方法就是:
以同样的方式,如果你想得到一个外部variables的值,你可以创build一个方法,返回你想要的!
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 }); }
你可以使用普通的lambdaexpression式 (“lambdaexpression式可以捕获variables”)
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是重构装饰器和适配器的好方法, 请看这里
我刚开始学习lambda,所以如果你发现一个错误,随时写评论。
我认为匿名类基本上像lambdaexpression式,但语法更糟…这是真实的,但语法更糟糕,导致(应该是)局部variables渗出到包含类。
您可以通过将它们放入父类的字段来访问最终的variables。
例如
接口:
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中sorting(我被困在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中进行更糟糕的devise,并重复自己更多,因为在Java中添加重复使用的代码+复杂性要比复制和粘贴大部分时间要糟糕。