内部类非最终变量java

时间:2012-07-03 18:26:57

标签: java inner-classes final local-variables

我需要更改内部类中的变量,并且我得到了臭名昭着的“无法引用在不同方法中定义的内部类中的非final变量”错误。

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 个答案:

答案 0 :(得分:9)

您可以简单地创建一个内部类而不是匿名类(就像您当前正在做的那样)。然后你有一个构造函数和你想要设置你的成员的任何其他方法。不需要任何黑客(如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
    }
}

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

答案 1 :(得分:2)

我在other thread here发布了类似的答案。基本上,我们的想法是创建一个“包装器”,它几乎包含任何Object类型。由于Java中的final代表“没有重新分配”而不是“常量”,所以这个技巧几乎可以解决。但正如原帖中所提到的,请确保在多线程环境中使用它时要小心。

答案 2 :(得分:0)

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

简而言之,如果内部类需要更改它,请将其作为内部类中的变量。

答案 3 :(得分:0)

由于您似乎设置了多个内容(来自注释),因此在主类button1WasClicked()中创建一个方法(更好的名称可能是doUpdate,doSave等等 - 与按钮的内容相关的内容),在那里放置正确的代码,并从内部类/监听器调用它。 (如果你使用Swing,我会把它变成一个Action,YMMV)

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