引用对象的使用和易产生bug的示例
来源:互联网 发布:淘宝买家秀福利怎么找 编辑:程序博客网 时间:2024/05/20 11:46
QuoteTest(引用对象技巧)
1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4 import java.util.Map; 5 6 /** 7 * Created by robin on 2016/4/13. 8 * 引用型对向操作总结: 9 * 1.被引用的对象,值改变时,会直接改变引用源的值; 10 * 2.当引用的对象,改变其引用源时,对其操作,只会改变新的引用源的值,并不会影响之前的引用源的值 11 * 3.从map中获取的引用不存在时,需要将新的引用put到map中,map中该位置的值,才会被引入 12 * @author robin 13 */ 14 public class QuoteTest { 15 16 public static void main(String args[]){ 17 Map<String,List<String>> map = new HashMap<String, List<String>>(); 18 for (int i =0;i< 5;i++){ 19 List<String> datalist = new ArrayList<String>(); 20 for (int j=0;j<10;j++){ 21 datalist.add(i*10+""+j); 22 } 23 map.put(""+i,datalist); 24 } 25 for (List<String> list:map.values()){ 26 System.out.println(listToString(list)); 27 } 28 System.out.println("----------分隔线1-----------"); 29 List<String> tempList = map.get("3"); 30 tempList.add("avc"); 31 tempList.remove("300"); 32 for (List<String> list:map.values()){ 33 System.out.println(listToString(list)); 34 } 35 System.out.println("----------分隔线2-----------"); 36 List<String> tempList2 = map.get("2");//tempList 获得map中 key为2的引用 37 List<String> replaceList = new ArrayList<String>(); 38 tempList2 = replaceList;////tempList 获得其他list的引用,失去map中 key为2的引用,此时对templist2做任何操作,影响的时replaceList引用的区域 39 tempList2.add("replaceList的值被改变"); 40 for (List<String> list:map.values()){ 41 System.out.println(listToString(list)); 42 } 43 System.out.println("replaceList的值:"+listToString(replaceList)); 44 System.out.println("----------分隔线3-----------"); 45 List<String> tempList3 = map.get("2"); 46 tempList3 = replaceList; 47 map.put("2",tempList3); 48 for (List<String> list:map.values()){ 49 System.out.println(listToString(list)); 50 } 51 System.out.println("----------分隔线4-----------"); 52 List<String> notExistList = map.get("5"); 53 if(notExistList == null){ 54 notExistList = new ArrayList<String>(); 55 } 56 notExistList.add("第5行数据添加进来..."); 57 for (List<String> list:map.values()){ 58 System.out.println(listToString(list)); 59 } 60 System.out.println("----------分隔线5-----------"); 61 List<String> notExistList2 = map.get("6"); 62 if(notExistList2 == null){ 63 notExistList2 = new ArrayList<String>(); 64 } 65 notExistList2.add("第6行数据添加进来..."); 66 map.put("6",notExistList2); 67 for (List<String> list:map.values()){ 68 System.out.println(listToString(list)); 69 } 70 System.out.println("----------分隔线5-----------"); 71 72 Map<String,Map<String,String>> mapOne = new HashMap<String, Map<String, String>>(); 73 String keyss = "mapTest"; 74 Map<String,String> mapTwo = new HashMap<String, String>(); 75 mapOne.put(keyss,mapTwo); 76 System.out.println("mapOne的数据:" + mapToString(mapOne)); 77 System.out.println("----------分隔线6-----------"); 78 mapTwo.put("aaa", "aaav"); 79 mapTwo.put("bbb", "bbbv"); 80 mapTwo.put("ccc","cccv"); 81 System.out.println("mapOne的数据:"+mapToString(mapOne)); 82 System.out.println("----------分隔线7-----------"); 83 } 84 85 private static String listToString(List<String> list){ 86 StringBuilder sb = new StringBuilder(""); 87 for (String s:list){ 88 sb.append("["+s+"] "); 89 } 90 return sb.toString(); 91 } 92 93 private static String mapToString(Map<?,?> map){ 94 StringBuilder sb = new StringBuilder(""); 95 for(Map.Entry entry:map.entrySet()){ 96 sb.append("[key:"+entry.getKey()+";value:"+entry.getValue()+"]"); 97 } 98 return sb.toString(); 99 }100 101 }
---------------------
引用对象易产生的bug:
2016.05.11
关于引用对象,使用不恰当,很容易给自己挖坑,产生非常严重的bug,进而导致整个系统实际业务的崩溃,而且这种bug很难被查出来。(如果日志记录不够详细,分析不够彻底,要找出这种bug,只能靠上帝保佑)
下面先上bug 代码 demo
1 import java.util.Iterator; 2 import java.util.List; 3 import java.util.Vector; 4 5 /** 6 * Created by robin on 2016/5/11. 7 * 8 * @author robin 9 */10 public class QuoteBugDemo {11 12 private static List<Integer> publicNums = new Vector<Integer>();13 14 public static void main(String args[]) throws InterruptedException {15 initPublicNums();//初始化公共数据源16 17 timeTask(1);//模拟执行定时任务118 19 timeTask(2);//模拟执行定时任务220 21 }22 23 24 private static void initPublicNums(){25 for (int i =0;i < 10;i++){26 publicNums.add(i);27 }28 }29 30 /**31 * 这块代码模拟的逻辑:32 * 1.每天获取配置好10个的数据源;33 * 2.检查这10个数据源,当数据源的数据准备好后,开始执行数据同步;34 * 3.从当天的带同步数据源list删除已经同步的数据;35 * @param mark36 * @throws InterruptedException37 */38 private static void timeTask(int mark) throws InterruptedException {39 final long start = System.currentTimeMillis();//程序开始运行时间40 //每天待同步数据源41 List<Integer> dataSources = publicNums;42 StringBuffer sb = new StringBuffer("mark("+mark+");公共数据源数目:"+dataSources.size()+";数据源列表[");43 for (Integer i:dataSources){44 sb.append(i+",");45 }46 sb.append("]");47 System.out.println("日志【"+sb.toString()+"】");48 while(true){49 long seconds = (System.currentTimeMillis() - start) / 1000;50 if(seconds > 15l){51 System.out.println("运行超过限定时间:15秒,退出");52 break;53 }54 Iterator<Integer> ite = dataSources.iterator();55 while (ite.hasNext()){//56 int dataSource = ite.next();57 boolean flag = isOk(dataSource);58 if(flag){//数据源数据已准备好59 System.out.println("对数据源:"+dataSource+"进行数据处理。");//同步数据60 ite.remove();//待同步数据源删除该数据源61 }62 }63 if(dataSources.size() != 0){64 Thread.sleep(1000);65 }else{66 break;67 }68 }69 System.out.println("定时任务mark["+mark+"]已经执行完毕");70 }71 72 /**73 * 模拟检查数据源是否OK74 * @param dataSource75 * @return76 */77 private static boolean isOk(int dataSource){78 if(dataSource%2 == 0){79 return true;80 }81 return false;82 }83 84 85 }
执行结果:
1 日志【mark(1);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】 2 对数据源:0进行数据处理。 3 对数据源:2进行数据处理。 4 对数据源:4进行数据处理。 5 对数据源:6进行数据处理。 6 对数据源:8进行数据处理。 7 运行超过限定时间:15秒,退出 8 定时任务mark[1]已经执行完毕 9 日志【mark(2);公共数据源数目:5;数据源列表[1,3,5,7,9,]】10 运行超过限定时间:15秒,退出11 定时任务mark[2]已经执行完毕
定时任务2,执行的时候,数据源只剩1,3,5,7,9。
改进方案:将公共数据源保护起来,仅提供公共数据源的副本:shallow copy和deep copy
核心代码:
1 /**2 * 改进方案1:获取公共数据源对象的副本3 * shallow copy:list中 元素引用 仍然是相同的4 * @return5 */6 private static List<Integer> getPublicNums(){7 List<Integer> clone = new ArrayList<Integer>(publicNums);8 return clone;9 }
改进后全部代码:
1 import java.util.ArrayList; 2 import java.util.Iterator; 3 import java.util.List; 4 import java.util.Vector; 5 6 /** 7 * Created by robin on 2016/5/11. 8 * 9 * @author robin10 */11 public class QuoteBugDemo {12 13 private static List<Integer> publicNums = new Vector<Integer>();14 15 public static void main(String args[]) throws InterruptedException {16 initPublicNums();//初始化公共数据源17 18 timeTask(1);//模拟执行定时任务119 20 timeTask(2);//模拟执行定时任务221 22 }23 24 25 private static void initPublicNums(){26 for (int i =0;i < 10;i++){27 publicNums.add(i);28 }29 }30 31 /**32 * 改进方案1:获取公共数据源对象的副本33 * shallow copy:list中 元素引用 仍然是相同的34 * @return35 */36 private static List<Integer> getPublicNums(){37 List<Integer> clone = new ArrayList<Integer>(publicNums);38 return clone;39 }40 41 /**42 * 这块代码模拟的逻辑:43 * 1.每天获取配置好10个的数据源;44 * 2.检查这10个数据源,当数据源的数据准备好后,开始执行数据同步;45 * 3.从当天的带同步数据源list删除已经同步的数据;46 * @param mark47 * @throws InterruptedException48 */49 private static void timeTask(int mark) throws InterruptedException {50 final long start = System.currentTimeMillis();//程序开始运行时间51 //每天待同步数据源52 List<Integer> dataSources = getPublicNums();//改进方案153 StringBuffer sb = new StringBuffer("mark("+mark+");公共数据源数目:"+dataSources.size()+";数据源列表[");54 for (Integer i:dataSources){55 sb.append(i+",");56 }57 sb.append("]");58 System.out.println("日志【"+sb.toString()+"】");59 while(true){60 long seconds = (System.currentTimeMillis() - start) / 1000;61 if(seconds > 15l){62 System.out.println("运行超过限定时间:15秒,退出");63 break;64 }65 Iterator<Integer> ite = dataSources.iterator();66 while (ite.hasNext()){//67 int dataSource = ite.next();68 boolean flag = isOk(dataSource);69 if(flag){//数据源数据已准备好70 System.out.println("对数据源:"+dataSource+"进行数据处理。");//同步数据71 ite.remove();//待同步数据源删除该数据源72 }73 }74 if(dataSources.size() != 0){75 Thread.sleep(1000);76 }else{77 break;78 }79 }80 System.out.println("定时任务mark["+mark+"]已经执行完毕");81 }82 83 /**84 * 模拟检查数据源是否OK85 * @param dataSource86 * @return87 */88 private static boolean isOk(int dataSource){89 if(dataSource%2 == 0){90 return true;91 }92 return false;93 }94 95 96 }
执行结果:
1 日志【mark(1);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】 2 对数据源:0进行数据处理。 3 对数据源:2进行数据处理。 4 对数据源:4进行数据处理。 5 对数据源:6进行数据处理。 6 对数据源:8进行数据处理。 7 运行超过限定时间:15秒,退出 8 定时任务mark[1]已经执行完毕 9 日志【mark(2);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】10 对数据源:0进行数据处理。11 对数据源:2进行数据处理。12 对数据源:4进行数据处理。13 对数据源:6进行数据处理。14 对数据源:8进行数据处理。15 运行超过限定时间:15秒,退出16 定时任务mark[2]已经执行完毕
0 0
- 引用对象的使用和易产生bug的示例
- C++产生的临时对象引用
- IOS库引用产生的bug - Apple LLVM 5.1 - Language
- Unity中使用LitJson产生的bug
- RaidoButton产生的bug
- bug产生的原因
- MFC临时对象的所产生的BUG
- 编程产生bug的原因
- Bug产生的原因有
- 安卓android中使用混淆proguard产生的bug
- android中使用原生WebSocket时产生的bug
- spring注解使用不当产生的一个Bug
- 引用之类对象的使用
- 简述JAVA对象的产生与使用
- 使用构造方法产生对象的原理
- 对象(实例)的产生和使用:
- OC类和对象-对象的产生和使用
- wallop 的一个bug 的产生条件
- Android USB转串口通信开发基本流程
- Java 集合 5:HashSet ,TreeSet 实现原理
- iOS打开闪光灯
- W88 Online Casino Malaysia sports Daily Reload(Online Casino Malaysia, sports Daily Reload, w88, W88
- MFC读写配置文件
- 引用对象的使用和易产生bug的示例
- js最新手机号码、电话号码正则表达式
- Ctrl与Caps Lock键(大写键)的交换swap
- php发送短信验证码
- 27. Remove Element
- Echarts导出为pdf格式
- c语言简单实现telnet客户端
- codis安装手册
- css元素水平居中