8

我需要更改内部类中的变量,然后我得到了臭名昭著的“无法引用以不同方法定义的内部类中的非最终变量”错误。

void onStart(){
  bt.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
       int q = i;
     }
  });
}

我很快创建了一个包含我想要更改的所有内容的类,并在内部类之外制作了该类的最终版本

class temp{
  int q;
}

void onStart(){
  final temp x = new temp();
  bt.setOnClickListener(new View.OnClickListener() {
     public void onClick(View v) {
       x.q = i;
     }
  });
}

这似乎是我需要的并且它有效,但我想知道这是否是正确解决问题的方法。另外,我真的很讨厌用这个词temp来命名我的班级。我所做的事情是否有一个实际的编程术语,以便我为我的班级取一个更具描述性的名称?

4

4 回答 4

9

您可以简单地创建一个内部类而不是匿名类(就像您目前正在做的那样)。然后你有一个构造函数和你想要设置你的成员的任何其他方法。无需 hackiness(如 1 个案例的数组)。

如果该类需要与其外部类进行任何数据交换,我会发现这个更清洁,但承认这是个人喜好。1 个成语的数组也可以,而且更简洁,但坦率地说,它看起来很丑。我通常将匿名内部类限制为只执行操作而不尝试更新外部类中的数据的那些。

例如:

private MyListener listener = new MyListener();

void onStart(){
  bt.setOnClickListener(listener);
}

class MyListener implements OnClickListener
{ 
    String name;
    int value;

    void setName(String newName)
    {
        name = newName;
    }

    void setValue(int newValue)
    {
        value = newValue;
    }

    public void onClick(View v) 
    {
        // Use the data for some unknown purpose
    }
}

如果涉及多个线程,则还必须使用适当的同步。

于 2012-07-03T19:23:28.817 回答
2

我在这里的另一个帖子中发布了类似的答案。基本上,这个想法是创建一个“包装器”,它可以包装几乎任何Object类型。因为final在 Java 中代表“不重新分配”而不是“恒定”,所以这个技巧非常有效。但正如原帖中提到的,在多线程环境中使用它时,请务必小心谨慎。

于 2012-07-03T18:30:34.797 回答
0

我会在外部类中保留对您的单击侦听器的引用,并使 int 成为侦听器中的成员变量。只需在单击时将变量存储在侦听器中,然后在需要时在外部类中获取变量,而不是在单击时设置它。

简单来说,如果内部类需要改变它,就让它成为内部类中的一个变量。

于 2012-07-03T19:31:42.607 回答
0

由于您似乎正在设置多项内容(来自评论),请在主类中创建一个方法button1WasClicked(),(更好的名称可能是 doUpdate、doSave 等 - 与按钮的功能相关),将正确的代码放在那里,并从内部类/侦听器中调用它。(如果您使用的是 Swing,我会将其设为 Action,YMMV)

这样,如果以后有一个菜单、一个意图或一个手势需要执行相同的东西,调用就在那里。

于 2012-07-03T19:43:15.347 回答