一个死循环导致的栈溢出实例:StackOverFlowError
2017-08-21 09:22
429 查看
有一个功能,要用复选框组做成单选框效果,如果有三个复选框 CheckBox ,并且保证每次只能选中一个。刚开始添加了以下的值改变后的监听方法 addValueChangeListener ,却导致了栈溢出:
思考上面代码的逻辑,假如现在第二个复选框是选中状态,此时再选中了第一个复选框,会触发第一个复选框的监听事件,第二、三个复选按钮就变成了未选中状态。因为第二个复选框的状态改变了,会触发它的监听事件,此时第一、三个复选框会变成选中状态。因为第一个已经是选中状态了,所以不会触发值改变的监听器。但是第三个复选框的状态却变了,触发监听器事件,把第一、二个监听器变成未选中状态。此时会再次触发第一个复选框的监听器事件。如此往复循环,StackOverFlowError
正确做法之一就是,不要在值改变的时候就触发事件,要在复选框的值变成选中状态时,触发一次事件就好了。添加以下判断。
这段代码还可以优化成一组复选框里只能选中一个值的方法,如下:
附录:
但是最开始的错误方法,如果只有两个CheckBox,就不会报错了
原因是:这两个监听器,每一个只能触发一个。
假如开始第二个复选框是选中状态,此时选中第一个复选框,触发第一个复选框的监听事件,把第二个复选框变成未选中状态。再触发第二个复选框的监听事件,此时把第一个复选框变成了选中状态。但是因为第一个复选框本身已经是选中状态了,所以它的值并没有改变,所以不会触发监听器事件。
原创文章,欢迎转载,转载请注明出处!
public static void checkBoxAddChangeListener(CheckBox checkBox1, CheckBox checkBox2, CheckBox checkBox3){ checkBox1.addValueChangeListener(e -> { checkBox2.setValue(!checkBox1.getValue()); checkBox3.setValue(!checkBox1.getValue()); }); checkBox2.addValueChangeListener(e -> { checkBox1.setValue(!checkBox2.getValue()); checkBox3.setValue(!checkBox2.getValue()); }); checkBox3.addValueChangeListener(e -> { checkBox1.setValue(!checkBox3.getValue()); checkBox2.setValue(!checkBox3.getValue()); }); }
思考上面代码的逻辑,假如现在第二个复选框是选中状态,此时再选中了第一个复选框,会触发第一个复选框的监听事件,第二、三个复选按钮就变成了未选中状态。因为第二个复选框的状态改变了,会触发它的监听事件,此时第一、三个复选框会变成选中状态。因为第一个已经是选中状态了,所以不会触发值改变的监听器。但是第三个复选框的状态却变了,触发监听器事件,把第一、二个监听器变成未选中状态。此时会再次触发第一个复选框的监听器事件。如此往复循环,StackOverFlowError
正确做法之一就是,不要在值改变的时候就触发事件,要在复选框的值变成选中状态时,触发一次事件就好了。添加以下判断。
public static void checkBoxAddChangeListener(CheckBox checkBox1, CheckBox checkBox2, CheckBox checkBox3){ checkBox1.addValueChangeListener(e -> { if(checkBox1.getValue()){ checkBox2.setValue(false); checkBox3.setValue(false); } }); checkBox2.addValueChangeListener(e -> { if(checkBox2.getValue()){ checkBox1.setValue(false); checkBox3.setValue(false); } }); checkBox3.addValueChangeListener(e -> { if(checkBox3.getValue()){ checkBox1.setValue(false); checkBox2.setValue(false); } }); }
这段代码还可以优化成一组复选框里只能选中一个值的方法,如下:
public static void checkBoxAddChangeListener(List<CheckBox> list){ for(int i=0; i<list.size(); i++){ CheckBox checkBox = list.get(i); checkBox.addValueChangeListener(e -> { if(checkBox.getValue()){ for (CheckBox tmp : list) { if (tmp == checkBox) { continue; } tmp.setValue(false); } } }); } }
附录:
但是最开始的错误方法,如果只有两个CheckBox,就不会报错了
public static void checkBoxAddChangeListener(CheckBox checkBox1, CheckBox checkBox2){ checkBox1.addValueChangeListener(e -> { checkBox2.setValue(!checkBox1.getValue()); }); checkBox2.addValueChangeListener(e -> { checkBox1.setValue(!checkBox2.getValue()); }); }
原因是:这两个监听器,每一个只能触发一个。
假如开始第二个复选框是选中状态,此时选中第一个复选框,触发第一个复选框的监听事件,把第二个复选框变成未选中状态。再触发第二个复选框的监听事件,此时把第一个复选框变成了选中状态。但是因为第一个复选框本身已经是选中状态了,所以它的值并没有改变,所以不会触发监听器事件。
原创文章,欢迎转载,转载请注明出处!
相关文章推荐
- 死循环导致java.lang.StackOverflowError -- 栈内存溢出
- Android开发中StackOverflowError错误实例分析
- 详细分析罕见的ClassCircularityError异常导致的StackOverflowError
- Android开发中StackOverflowError错误实例分析
- 【C#】解决lucene.net在建立索引的时候,出现“算数运算导致溢出”stackoverflow exception的错误
- Android开发中StackOverflowError错误实例分析
- 因为new一个类而导致:StackOverflowError
- 类的相互依赖导致StackOverflowError
- 递归错误之栈溢出Exception in thread "main" java.lang.StackOverflowError
- Android布局嵌套太深导致的错误:StackOverflowError
- JVM异常之:栈溢出StackOverflowError
- Tomcat 7.0.3x 启动时遇到StackOverflowError导致失败的解决办法
- Android开发中StackOverflowError错误实例分析
- 记录一次项目引用导致的StackOverflowError
- 类的相互依赖导致StackOverflowError
- Tomcat 7.0.3x 启动时遇到StackOverflowError导致失败的解决办法
- 慎用subList:ArrayList$SubList.add导致的java.lang.StackOverflowError
- 一个StackOverFlowError
- java编程题:写代码实现一个StackOverFlowError和OutOfMemoryError
- jpa多对多映射时(@ManyToMany)时堆溢出(java.lang.StackOverflowError: null )