一个死循环导致的栈溢出实例:StackOverFlowError
有一个功能,要用复选框组做成单选框效果,如果有三个复选框 CheckBox ,并且保证每次只能选中一个。刚开始添加了以下的值改变后的监听方法 addValueChangeListener ,却导致了栈溢出:
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());
});
}
原因是:这两个监听器,每一个只能触发一个。
假如开始第二个复选框是选中状态,此时选中第一个复选框,触发第一个复选框的监听事件,把第二个复选框变成未选中状态。再触发第二个复选框的监听事件,此时把第一个复选框变成了选中状态。但是因为第一个复选框本身已经是选中状态了,所以它的值并没有改变,所以不会触发监听器事件。
原创文章,欢迎转载,转载请注明出处!
一个死循环导致的栈溢出实例:StackOverFlowError的更多相关文章
- linux 内核假死循环导致的问题
[, comm: -IFileSender Tainted: G B ENX -- ZTE Grantley/S1008 [:[<ffffffff810fb2cb>] [<fffff ...
- PureMVC和Unity3D的UGUI制作一个简单的员工管理系统实例
前言: 1.关于PureMVC: MVC框架在很多项目当中拥有广泛的应用,很多时候做项目前人开坑开了一半就消失了,后人为了填补各种的坑就遭殃的不得了.嘛,程序猿大家都不喜欢像文案策划一样组织文字写东西 ...
- 一个简单的Android小实例
原文:一个简单的Android小实例 一.配置环境 1.下载intellij idea15 2.安装Android SDK,通过Android SDK管理器安装或卸载Android平台 3.安装J ...
- 初学redux笔记,及一个最简单的redux实例
categories: 笔记 tags: react redux 前端框架 把初学redux的一些笔记写了下来 分享一个入学redux很合适的demo, 用redux实现计数器 这是从阮一峰老师git ...
- 一个简单的jQuery插件开发实例
两年前写的一个简单的jQuery插件开发实例,还是可以看看的: <script type="text/javascript" src="jquery-1.7.2.m ...
- [WCF REST] 一个简单的REST服务实例
Get:http://www.cnblogs.com/artech/archive/2012/02/04/wcf-rest-sample.html [01] 一个简单的REST服务实例 [02] We ...
- 10-多写一个@Autowired导致程序崩了
再是javaweb实验六中,是让我们改代码,让它跑起来,结果我少注释了一个,导致一直报错,检查许久没有找到,最后通过代码替换逐步查找,才发现问题.
- this.$Message.success('提示信息') 少写了一个c 导致报错
this.$Message.success('提示信息') 少写了一个c 导致报错 而且 $Message 输出还没显示,导致我以为是没有 $Message 对象了,其实全局对象直接调用即可
- 如何将RAC数据库的 RMAN Disk 备份 Restore 到另一个节点上的单个实例 (Doc ID 415579.1)
HowTo Restore RMAN Disk backups of RAC Database to Single Instance On Another Node (Doc ID 415579.1) ...
随机推荐
- AIS系统(转)
船舶自动识别系统(Automatic Identification System, 简称AIS系统)由岸基(基站)设施和船载设备共同组成,是一种新型的集网络技术.现代通讯技术.计算机技术.电子信息显示 ...
- Java实现几种常见排序方法
日常操作中常见的排序方法有:冒泡排序.快速排序.选择排序.插入排序.希尔排序,甚至还有基数排序.鸡尾酒排序.桶排序.鸽巢排序.归并排序等. 以下常见算法的定义 1. 插入排序:插入排序基本操作就是将一 ...
- oracle 记录被另一个用户锁住
第一步:查询处用户,被锁表名,sessionID select b.owner,b.object_name,l.session_id,l.locked_modefrom v$locked_object ...
- [01] AJAX
1.概述 AJAX,"Asynchronous JavaScript And XML"的简称,即"异步的JavaScript和XML".AJAX的作用在于页面中 ...
- 如何让.NET Core支持GB2312和GBK
在.NET Core中,默认是不支持GB2312和GBK编码的. 例如我们如果新建一个.NET Core控制台项目,然后在其Main方法中使用如下代码: using System; using Sys ...
- 【nodejs】让nodejs像后端mvc框架(asp.net mvc )一样处理请求--控制器的声明定义和发现篇(3/8)
文章目录 前情概要 前面文章把路由已经介绍的差不多了,包括url映射,路由选择等.接下来讲一讲controller的一些基本规则 BaseController的所有代码都在这里拉.相当简单. 主要逻辑 ...
- nginx负载均衡(5种方式)、rewrite重写规则及多server反代配置梳理
Nginx除了可以用作web服务器外,他还可以用来做高性能的反向代理服务器,它能提供稳定高效的负载均衡解决方案.nginx可以用轮询.IP哈希.URL哈希等方式调度后端服务器,同时也能提供健康检查功能 ...
- let命令和块级作用域
学习了阮一峰老师的ES6,http://es6.ruanyifeng.com/,收益良多. 一.let命令1.概念:let命令用于声明变量,和var类似,但是使用let命令所声明的变量只有在该变量所在 ...
- 第三个spring冲刺第2天
今天我们有了计时功能的实现,并且在考虑如何使得计时器美观好看达到我们的要求,对此我们换了不同的背景,时钟框,效果还有待查看.
- GCP试用到期再申请
目标 GCP的免费试用到期了.网传可以续用,看了教程,记录下来. 法一 应该可以直接用一个新gmail账号的.这个方法的难点可能在于注册新账号有门槛.我有一个很久以前注册过的,试着找回了密码,登入GC ...