一个死循环导致的栈溢出实例: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) ...
随机推荐
- Android中AsyncTask的使用
原文 https://blog.csdn.net/liuhe688/article/details/6532519 在Android中实现异步任务机制有两种方式,Handler和AsyncTask. ...
- IDEA注册jar包使用和常用插件
IDEA注册jar包使用 点击获取下载地址或生成注册码 一.安装完成后,先不启动,首先如下图修改相关的地方. 二.启动IDEA,并且激活IDEA IDEA插件仓库 IntelliJ IDEA Plug ...
- TCP/IP协议--TCP的超时和重传
TCP是可靠传输.可靠之一体现在收到数据后,返回去一个确认.但是不能完全避免的是,数据和确认都可能丢失.解决这个办法就是,提供一个发送的重传定时器:如果定时器溢出时还没收到确认,它就重传这个报文段. ...
- odoo系统中name_search和name_get用法
自动带出工序和工序序号,两个条件都能搜索,并且两个都带出来显示在前端: # 输入工序序号会自动带出工序名// def name_search(self, cr,user,name='', args=N ...
- 阿里巴巴Java开发规约插件p3c详细教程及使用感受 - 转
http://www.cnblogs.com/han-1034683568/p/7682594.html
- 在线排错之curl命令详解
春回大地万物复苏,好久不来,向各位博友问好. 简介 cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行.它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下 ...
- 【下一代核心技术DevOps】:(六)Rancher集中存储及相关应用
1. 前言 为什么要使用集中存储? 使用集中存储有个很大的优势是数据安全和统一管理,和集群完美配合. 产品集成存储经历过几个阶段: 1.单机本机存储. 系统使用本地硬盘存储 2.单网络集中存储. 局域 ...
- Nginx挂载维护页或返回自定义响应信息
在服务停机升级或者服务暂不可用时,往往希望能够返回给用户更为明确和友好的响应信息.可以通过修改nginx配置文件,达到返回自定义信息的效果.有如下几种配置方式: (1)Nginx接收到的所有请求,都返 ...
- 12.17 Daily Scrum
Today's Task Tomorrow's Task 丁辛 实现和菜谱相关的餐厅列表. 实现和菜谱相关的餐厅列表. 邓亚梅 美化搜索框UI. 美 ...
- 自己搭建的一个react脚手架
包括了: react.react router(v4), webpack(v4),echarts, google的组件库material ui, 后期会加上redux但是这些做中小型系统已经够了,de ...