热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

引用对象的使用和易产生bug的示例

本文属原创,转载请注明出处:http:www.cnblogs.comrobinjava77p5481608.html(Robin)QuoteTest(引用对象技巧)1impor

本文属原创,转载请注明出处:http://www.cnblogs.com/robinjava77/p/5481608.html  (Robin)

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> map = new HashMap>();
18 for (int i =0;i<5;i++){
19 List datalist = new ArrayList();
20 for (int j=0;j<10;j++){
21 datalist.add(i*10+""+j);
22 }
23 map.put(""+i,datalist);
24 }
25 for (List list:map.values()){
26 System.out.println(listToString(list));
27 }
28 System.out.println("----------分隔线1-----------");
29 List tempList = map.get("3");
30 tempList.add("avc");
31 tempList.remove("300");
32 for (List list:map.values()){
33 System.out.println(listToString(list));
34 }
35 System.out.println("----------分隔线2-----------");
36 List tempList2 = map.get("2");//tempList 获得map中 key为2的引用
37 List replaceList = new ArrayList();
38 tempList2 = replaceList;////tempList 获得其他list的引用,失去map中 key为2的引用,此时对templist2做任何操作,影响的时replaceList引用的区域
39 tempList2.add("replaceList的值被改变");
40 for (List list:map.values()){
41 System.out.println(listToString(list));
42 }
43 System.out.println("replaceList的值:"+listToString(replaceList));
44 System.out.println("----------分隔线3-----------");
45 List tempList3 = map.get("2");
46 tempList3 = replaceList;
47 map.put("2",tempList3);
48 for (List list:map.values()){
49 System.out.println(listToString(list));
50 }
51 System.out.println("----------分隔线4-----------");
52 List notExistList = map.get("5");
53 if(notExistList == null){
54 notExistList = new ArrayList();
55 }
56 notExistList.add("第5行数据添加进来...");
57 for (List list:map.values()){
58 System.out.println(listToString(list));
59 }
60 System.out.println("----------分隔线5-----------");
61 List notExistList2 = map.get("6");
62 if(notExistList2 == null){
63 notExistList2 = new ArrayList();
64 }
65 notExistList2.add("第6行数据添加进来...");
66 map.put("6",notExistList2);
67 for (List list:map.values()){
68 System.out.println(listToString(list));
69 }
70 System.out.println("----------分隔线5-----------");
71
72 Map> mapOne= new HashMap>();
73 String keyss = "mapTest";
74 Map mapTwo = new HashMap();
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 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 publicNums = new Vector();
13
14 public static void main(String args[]) throws InterruptedException {
15 initPublicNums();//初始化公共数据源
16
17 timeTask(1);//模拟执行定时任务1
18
19 timeTask(2);//模拟执行定时任务2
20
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 mark
36 * @throws InterruptedException
37 */
38 private static void timeTask(int mark) throws InterruptedException {
39 final long start = System.currentTimeMillis();//程序开始运行时间
40 //每天待同步数据源
41 List 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 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 * 模拟检查数据源是否OK
74 * @param dataSource
75 * @return
76 */
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 * @return
5 */
6 private static List getPublicNums(){
7 List clOne= new ArrayList(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 robin
10 */
11 public class QuoteBugDemo {
12
13 private static List publicNums = new Vector();
14
15 public static void main(String args[]) throws InterruptedException {
16 initPublicNums();//初始化公共数据源
17
18 timeTask(1);//模拟执行定时任务1
19
20 timeTask(2);//模拟执行定时任务2
21
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 * @return
35 */
36 private static List getPublicNums(){
37 List clOne= new ArrayList(publicNums);
38 return clone;
39 }
40
41 /**
42 * 这块代码模拟的逻辑:
43 * 1.每天获取配置好10个的数据源;
44 * 2.检查这10个数据源,当数据源的数据准备好后,开始执行数据同步;
45 * 3.从当天的带同步数据源list删除已经同步的数据;
46 * @param mark
47 * @throws InterruptedException
48 */
49 private static void timeTask(int mark) throws InterruptedException {
50 final long start = System.currentTimeMillis();//程序开始运行时间
51 //每天待同步数据源
52 List dataSources = getPublicNums();//改进方案1
53 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 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 * 模拟检查数据源是否OK
85 * @param dataSource
86 * @return
87 */
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]已经执行完毕

已达预期。

------------------------------------------

shallow copy 和 deep copy 的区别详见我的另一篇博客:http://www.cnblogs.com/robinjava77/p/5481874.html 

 


推荐阅读
  • C#实现文件的压缩与解压
    2019独角兽企业重金招聘Python工程师标准一、准备工作1、下载ICSharpCode.SharpZipLib.dll文件2、项目中引用这个dll二、文件压缩与解压共用类 ... [详细]
  • java解析json转Map前段时间在做json报文处理的时候,写了一个针对不同格式json转map的处理工具方法,总结记录如下:1、单节点单层级、单节点多层级json转mapim ... [详细]
  • 本文详细介绍了如何使用JavaScript实现面部交换功能,包括基本原理和具体实现步骤。 ... [详细]
  • 本文详细介绍了 com.apollographql.apollo.api.internal.Optional 类中的 orNull() 方法,并提供了多个实际代码示例,帮助开发者更好地理解和使用该方法。 ... [详细]
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • 本文节选自《NLTK基础教程——用NLTK和Python库构建机器学习应用》一书的第1章第1.2节,作者Nitin Hardeniya。本文将带领读者快速了解Python的基础知识,为后续的机器学习应用打下坚实的基础。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • 本文介绍了在 Java 编程中遇到的一个常见错误:对象无法转换为 long 类型,并提供了详细的解决方案。 ... [详细]
  • com.sun.javadoc.PackageDoc.exceptions()方法的使用及代码示例 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 属性类 `Properties` 是 `Hashtable` 类的子类,用于存储键值对形式的数据。该类在 Java 中广泛应用于配置文件的读取与写入,支持字符串类型的键和值。通过 `Properties` 类,开发者可以方便地进行配置信息的管理,确保应用程序的灵活性和可维护性。此外,`Properties` 类还提供了加载和保存属性文件的方法,使其在实际开发中具有较高的实用价值。 ... [详细]
  • 使用Tkinter构建51Ape无损音乐爬虫UI
    本文介绍了如何使用Python的内置模块Tkinter来构建一个简单的用户界面,用于爬取51Ape网站上的无损音乐百度云链接。虽然Tkinter入门相对简单,但在实际开发过程中由于文档不足可能会带来一些不便。 ... [详细]
  • 深入解析 Lifecycle 的实现原理
    本文将详细介绍 Android Jetpack 中 Lifecycle 组件的实现原理,帮助开发者更好地理解和使用 Lifecycle,避免常见的内存泄漏问题。 ... [详细]
  • Flowable 流程图路径与节点展示:已执行节点高亮红色标记,增强可视化效果
    在Flowable流程图中,通常仅显示当前节点,而路径则需自行获取。特别是在多次驳回的情况下,节点可能会出现混乱。本文重点探讨了如何准确地展示流程图效果,包括已结束的流程和正在执行的流程。具体实现方法包括生成带有高亮红色标记的图片,以增强可视化效果,确保用户能够清晰地了解每个节点的状态。 ... [详细]
  • 如何使用 `org.eclipse.rdf4j.query.impl.MapBindingSet.getValue()` 方法及其代码示例详解 ... [详细]
author-avatar
喏焿你一辈子_997
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有