zoukankan      html  css  js  c++  java
  • 一个死循环导致的栈溢出实例:StackOverFlowError

      有一个功能,要用复选框组做成单选框效果,如果有三个复选框 CheckBox ,并且保证每次只能选中一个。刚开始添加了以下的值改变后的监听方法 addValueChangeListener ,却导致了栈溢出:

     1 public static void checkBoxAddChangeListener(CheckBox checkBox1, CheckBox checkBox2, CheckBox checkBox3){
     2     checkBox1.addValueChangeListener(e -> {
     3         checkBox2.setValue(!checkBox1.getValue());
     4         checkBox3.setValue(!checkBox1.getValue());
     5     });
     6 
     7     checkBox2.addValueChangeListener(e -> {
     8         checkBox1.setValue(!checkBox2.getValue());
     9         checkBox3.setValue(!checkBox2.getValue());
    10     });
    11 
    12     checkBox3.addValueChangeListener(e -> {
    13         checkBox1.setValue(!checkBox3.getValue());
    14         checkBox2.setValue(!checkBox3.getValue());
    15     });
    16 }

      思考上面代码的逻辑,假如现在第二个复选框是选中状态,此时再选中了第一个复选框,会触发第一个复选框的监听事件,第二、三个复选按钮就变成了未选中状态。因为第二个复选框的状态改变了,会触发它的监听事件,此时第一、三个复选框会变成选中状态。因为第一个已经是选中状态了,所以不会触发值改变的监听器。但是第三个复选框的状态却变了,触发监听器事件,把第一、二个监听器变成未选中状态。此时会再次触发第一个复选框的监听器事件。如此往复循环,StackOverFlowError

      正确做法之一就是,不要在值改变的时候就触发事件,要在复选框的值变成选中状态时,触发一次事件就好了。添加以下判断。

     1 public static void checkBoxAddChangeListener(CheckBox checkBox1, CheckBox checkBox2, CheckBox checkBox3){
     2     checkBox1.addValueChangeListener(e -> {
     3         if(checkBox1.getValue()){
     4             checkBox2.setValue(false);
     5             checkBox3.setValue(false);
     6         }
     7     });
     8 
     9     checkBox2.addValueChangeListener(e -> {
    10         if(checkBox2.getValue()){
    11             checkBox1.setValue(false);
    12             checkBox3.setValue(false);
    13         }
    14     });
    15 
    16     checkBox3.addValueChangeListener(e -> {
    17         if(checkBox3.getValue()){
    18             checkBox1.setValue(false);
    19             checkBox2.setValue(false);
    20         }
    21     });
    22 }

      这段代码还可以优化成一组复选框里只能选中一个值的方法,如下: 

    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());
        });
    }

      原因是:这两个监听器,每一个只能触发一个。
      假如开始第二个复选框是选中状态,此时选中第一个复选框,触发第一个复选框的监听事件,把第二个复选框变成未选中状态。再触发第二个复选框的监听事件,此时把第一个复选框变成了选中状态。但是因为第一个复选框本身已经是选中状态了,所以它的值并没有改变,所以不会触发监听器事件。

      原创文章,欢迎转载,转载请注明出处!

  • 相关阅读:
    第十九节,使用RNN实现一个退位减法器
    深度学习系列经典博客收藏
    第十八节,TensorFlow中使用批量归一化(BN)
    第十七节,深度学习模型的训练技巧-优化卷积核,多通道卷积
    第十六节,使用函数封装库tf.contrib.layers
    第十五节,利用反卷积技术复原卷积网络各层图像
    第十四节,TensorFlow中的反卷积,反池化操作以及gradients的使用
    第十三节,使用带有全局平均池化层的CNN对CIFAR10数据集分类
    第十二节,TensorFlow读取数据的几种方法以及队列的使用
    在hadoop集群添加了slave节点的方法
  • 原文地址:https://www.cnblogs.com/acm-bingzi/p/stackOverFlowError.html
Copyright © 2011-2022 走看看