4

有一个快速的问题,我希望有人能回答。基本上我有一个字符串变量,它需要根据组合框中的值进行更改,该组合框中附加了一个事件侦听器。但是,如果我将字符串设为 final,则无法更改,但如果我不将其设为 final,则 eclipse 会抱怨它不是最终的。什么是最好的(也是最简单的)解决方法?

代码如下

final String dialogOutCome = "";

//create a listener for the combo box
Listener selection = new Listener() {

    public void handleEvent(Event event) {
    //get the value from the combo box
    String comboVal = combo.getText();

    switch (comboVal) {
         case "A": dialogOutCome = "a";
         case "B": dialogOutCome = "b";
         case "C": dialogOutCome = "c";
         case "D": dialogOutCome = "d";
    }
   }
};
4

6 回答 6

5

你不能。

考虑一下:

  • 只要在运行中声明的方法,局部变量就存在。
  • 一旦该方法调用结束(通常是因为该方法存在),变量就会消失
  • 听众可以(而且通常确实)活得更久

那么当方法已经返回并且侦听器尝试修改局部变量时会发生什么?

因为这个问题没有一个很好的答案,他们决定通过不允许访问非final局部变量来使这种情况变得不可能。

有两种方法可以解决这个问题:

  • 尝试更改字段而不是局部变量(这可能也更适合侦听器的生命周期)
  • 使用final局部变量,您可以更改其中的内容(例如 aListString[]带有单个元素的 a)。
于 2013-01-17T15:15:06.607 回答
3

These answers are all telling you how to make a flawed approach "work" at a superficial level.

The real problem is that you're trying to apply traditional, synchronous, "call/return" coding patterns to a library that doesn't support it. The real answer is that when the event you're waiting for happens asynchronously, the stuff you want to do after the event has to happen asynchronously as well. Understanding the event-driven nature of Swing is vital to being effective in it.

In other words, think of what piece of code will read dialogOutCome. Will some action be performed? If so, perform that action from the handler (or as a result of the handler) instead.

于 2013-01-17T15:20:58.207 回答
2

另一种方法是使用这种方法。

public class ReturnValueListener implements Listener {

    private String dialogOutCome;

    public void handleEvent(Event event) {
        //get the value from the combo box
        String comboVal = combo.getText();

        switch (comboVal) {
            case "A": dialogOutCome = " gay";
            ase "B": dialogOutCome = " ugly";
            case "C": dialogOutCome = " smelly";
            case "D": dialogOutCome = " great";
        }
    }

    public String getDialogOutCome() {
        return dialogOutCome;
    }
}

Listener selection = new ReturnValueListener();
//Set my listener somewhere,
....registerListener(selection);
//After my handleEvent is called
String dialogOutCome = selection.getDialogOutCome();
于 2013-01-17T15:15:24.107 回答
1

只需创建简单的StringWrapper对象:

static class StringWrapper {
       String value;

       StringWrapper(String value) {
           this.value = value;
       } 
}

并在字段类型中使用它dialogOutCome

final StringWrapper dialogOutCome = new StringWrapper("");

Listener selection = new Listener() {

    public void handleEvent(Event event) {
        String comboVal = combo.getText();

        switch (comboVal) {
          case "A": dialogOutCome.value = " gay";
          case "B": dialogOutCome.value = " ugly";
          case "C": dialogOutCome.value = " smelly";
          case "D": dialogOutCome.value = " great";
        }
   }
};
于 2013-01-17T15:14:39.313 回答
0

您可以使用 setter 进行间接寻址。这将消除最后的限制(因为您访问的字段是“this”而不是“dialogOutcome”。

String dialogOutCome = "";

void setOutcome(String value){
  dialogOutCome = value;
}

//create a listener for the combo box
Listener selection = new Listener() {

    public void handleEvent(Event event) {
    //get the value from the combo box
    String comboVal = combo.getText();

    switch (comboVal) {
         case "A": setOutcome(" gay");
         case "B": setOutcome(" ugly");
         case "C": setOutcome(" smelly");
         case "D": setOutcome(" great");
    }
   }
};
于 2013-01-17T15:18:12.470 回答
-2

解决方法:使用StringBuilder而不是String. 当然,StringBuilder不能改变 中的引用handleEvent,但我们可以调用它的方法。

    final StringBuilder sb = new StringBuilder();

    Listener selection = new Listener() {

        public void handleEvent(Event event) {
        ...
        switch (comboVal) {
             case "A": sb.delete(0, sb.length()).append("a");
             case "B": sb.delete(0, sb.length()).append("b");
            ...
        }
       }
    };

...
System.out.println(sb.toString());

然后你可以通过StringBuilder.toString();

编辑:请提供否决这个答案的原因。

于 2013-01-17T15:20:19.523 回答