如何将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中添加重复使用的代码+复杂性要比复制和粘贴大部分时间要糟糕。