一直报错Local variable p1 defined in an enclosing scope must be final or effectively final

代码简化如下:
class xx{
.......
Vector<actionQuery> queryList=new Vector<actionQuery>();
for(int p1=0;p1<table.getColumnCount();p1++){
queryList.add(new actionQuery(table,p1));
menuItem.get(p1).addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
queryList.get(p1).actionQueryPerform();
}
class actionQuery{
public actionQuery(JTable table,int k){....}
public void actionQueryPerform(){.....}
}
其实是一个菜单,菜单中每个item有个事件,但是需要向下一个类传递参数

p1必须是一个final的变量,匿名对象里面存在一种风险,就是内部对象在使用外部对象的变量时,其依赖的对象已被销毁导致变量为空,因此必须用final申明p1,因为你使用的局部变量在初始化后,又对这个变量进行了赋值。赋值后会认为这个变量不是final了,所以报错,针对这个问题可以有以下几种解决办法。

方法一:

List<String> list = new ArrayList<String>();

list.add("name");

list.add("age");

list.add("address");

boolean flag = true;

flag = false;

boolean newFlag = flag;

list.stream().forEach(e -> {

if (newFlag) {

System.out.println(e);

}

});

即将你想要使用的局部变量,在使用前赋值给一个新的变量,这样java8会认为这个新的变量是final,没有变化的,可以使用。

方法二:

List<String> list = new ArrayList<String>();

list.add("name");

list.add("age");

list.add("address");

boolean[] flag = {true};

flag[0] = false;

list.stream().forEach(e -> {

if (flag[0]) {

System.out.println(e);

}

});

将你需要的值放到一个数组里,也可以使用。

扩展资料:

注意事项

1、Lambda表达式与匿名内部类一样,都可以直接访问“effectively final”的局部变量,以及外部类的成员变量。

2、Lambda表达式创建的对象与匿名内部类生成的对象一样,都可以直接调用从接口中继承的默认方法。

3、由于Lambda表达式访问了finalName的局部变量,因此该局部变量相当于有一个final修饰,所以不能重新赋值。

温馨提示:内容为网友见解,仅供参考
第1个回答  2017-11-14
class actionQuery{
    public actionQuery(final JTable table,final int k){....}
    public void actionQueryPerform(){.....}
}

使用final修饰即可。。。

追问

好像不对,主要是在事件监听里面使用vector.get(p1)出现问题,p1是循环里面的变量

第2个回答  2017-11-14
错误信息已经说了p1必须是一个final的变量,匿名对象里面存在一种风险,就是内部对象在使用外部对象的变量时,其依赖的对象已被销毁导致变量为空,因此必须用final申明p1本回答被提问者采纳

...defined in an enclosing scope must be final or effectively final...
p1必须是一个final的变量,匿名对象里面存在一种风险,就是内部对象在使用外部对象的变量时,其依赖的对象已被销毁导致变量为空,因此必须用final申明p1,因为你使用的局部变量在初始化后,又对这个变量进行了赋值。赋值后会认为这个变量不是final了,所以报错,针对这个问题可以有以下几种解决办法。方法一...

相似回答