一、背景
之前我好多次谈到:“每一个疑问背后至少有一个知识盲区,隐藏着一次极佳的学习机会”。
今天结合一个具体的案例,谈谈这个观念,顺便谈谈如何正确提问。
今天有一个朋友问到:
请教一个问题 为什么用lombox的build构建一个对象内部持有的另外一个对象 用io的方式进行深克隆 拿到的两个内部对象是一样的 但是如果用set的方式给内部持有对象赋值 深克隆出来的就不是同一个对象
二、解答过程
2.1 存在的问题
首先这段描述不太清楚,没有标点。描述的问题显然和深拷贝的概念不符,但是描述的内容无法让解答的人有足够的线索能够为他解答问题。
2.2 引导
因此给出下面的回复:
1 先确认自己理解了 浅拷贝和深拷贝的概念
(之前一直强调的,是什么,为什么比怎么做更重要)
2 建议你写一个简单的模拟的例子再发出来方便讨论,因为部分描述不太容易理解甚至有歧义
比如
“用io的方式进行深克隆 拿到的两个内部对象是一样的” 一样的是指同一个对象?啥样的IO方式?怎么实现深克隆的?
“set的方式给内部持有对象赋值” 是set内部对象,还是set内部对象的属性
给出的进一步建议:
建议可以用commons-lang3 的 SerializationUtils.serialize 序列化为字节数组 SerializationUtils.deserialize反序列化为对象。(怕他序列化姿势有问题)
写个DEMO表达的更清楚一些(方便进一步分析问题)
然后该同学发来了代码:
附件类:
import java.io.Serializable; @Data @AllArgsConstructor public class Attchment implements Serializable { private String name; }
待测试类:
import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.*; @Data @Builder @NoArgsConstructor @AllArgsConstructor public class WeeklyLogByIO implements Serializable { private String name; private String date; private String content; private Attchment attchment; public WeeklyLogByIO deepClone() throws Exception{ //将对象写入到流中 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); //将对象从流中取出 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (WeeklyLogByIO)ois.readObject(); } }
测试代码:
public class SDemo { public static void main(String[] args) { WeeklyLogByIO logProvious = new WeeklyLogByIO(); Attchment attchment = new Attchment("附件1"); logProvious.builder().attchment(attchment).build(); //logProvious.setAttchment(attchment); //开始克隆 WeeklyLogByIO weekNew = null; try { weekNew = logProvious.deepClone(); } catch (Exception e) { e.printStackTrace(); } weekNew.setDate("第二周"); System.out.println(logProvious == weekNew); System.out.println(logProvious.getAttchment() == weekNew.getAttchment()); } }
输出的结果分别为 false 和 true。
和对方确认他的表达:
你表达的就是 为啥深拷贝,结果一个是 true 一个是 false 对吧,就是第二个打印语句输出的结果不对对吧?
这才清楚明白地搞清楚他真正想表达的意思。
看了DEMO 得出了两个结论:
1、 因为你builder 模式使用姿势不对。builder 是静态函数 不需要用实例去调用 , build 之后返回值构造了新的对象 你并没有拿对象去接收。
2、 你没认真调试代码。在第二个打印语句处断点调试,就可以看到附件并没有设置,两个都是null 所以输出 true。
3、没认真看IDE的警告。通过类实例调用静态函数会有警告的。
修改一行解决问题:
public class SDemo { public static void main(String[] args) { Attchment attchment = new Attchment("附件1"); WeeklyLogByIO logProvious = WeeklyLogByIO.builder().attchment(attchment).build(); //logProvious.setAttchment(attchment); //开始克隆 WeeklyLogByIO weekNew = null; try { weekNew = logProvious.deepClone(); } catch (Exception e) { e.printStackTrace(); } weekNew.setDate("第二周"); System.out.println(logProvious == weekNew); System.out.println(logProvious.getAttchment() == weekNew.getAttchment()); } }
然后该同学表明确实不熟悉 builder 模式,而且不熟悉 lombok。
然后我给出建议:
1、学习Builder模式
2、看 lombok官方文档
3、直接使用反编译工具,查看lombok 注解编译生成的类文件的反编译后的”源码”就可以查看注解对源码的影响。
三、看到了什么
3.1 方法的重要性
其实很多人编程过程中遇到问题的主要原因是学习技术不求甚解,大概看看博客,看看别人怎么用就用,没有认真看官方技术文档,没有能够通过更丰富的手段来学习这种技术。
所以很多人想要有较大进步,并不像一些人所想的那样,“更加努力”,而是找到更加科学的方法。
另外我们还看到“很多人觉得某些技术没用,就不愿意学,很多时候正是因为没学好,才在该用到的时候想不着用”。
比如我们可以通过反编译来学习 lombok, 然而很多人想不到用,甚至从来都没尝试过反编译。
3.2 如何提问
另外很多人提问都不是很清楚,对解决问题的人造成很大困难。当然我是希望大家能够自己解决问题,这非常重要,没有人可以一直帮你解决问题,工作之后排错的能力更加重要。
1、提问时要尽可能地有条理表达自己的疑问,带上序号,带上标点,描述清楚前因后果,描述清楚核心困惑等。
2、提问之前自己一定要进行思考,提问之前一定要自己调试过,提问之前一定要自己百度过
3、提问时尽可能给出详细的线索,比如报错的具体内容,比如给出源码,比如 Web 项目 F12看网络给出请求和响应状态等。
3.3 每一个盲点背后
每一个困惑背后至少有一个知识盲区,隐藏着一次极佳的学习机会。
该同学通过这个问题的解答,意识到了 builder 设计模式理解不到位,意识到了 lombok 注解了解的不到位。
学到了可以通过反编译来查看 lombok 注解对源码的影响,直观和快速地学习 lombok 注解。
如果是一个聪明的有心人,应该意识到自己解决问题的能力有待提高,自己连起码的断点调试都没有做。
如果是一个聪明的有心人,应该会意识到今后要重视 IDE的警告,甚至安装上推荐的 阿里巴巴 Java 开发规范的配套插件。
如果是一个聪明的有心人,应该可以从我的回答中了解到 commons-lang3 有更简洁地实现序列化和反序列化的工具类,进而了解 commons-lang3 中的其他好用的工具类从而提高开发效率。
如果是一个聪明的有心人,应该能够意识到自己提问的姿势有问题,后续提问应该更有条理,更准确的表达自己的问题。
如果是一个聪明的有心人,应该...
如果真正可以意识到这些问题,并能够较快改正,学习的速度会有极大的提升。
四、总结
希望越来越多的同学能够意识到方法的重要性。
希望也来越多的同学能够知道如何提问。
希望越来越多的同学能够意识到:每一个困惑背后至少有一个知识盲区,隐藏着一次极佳的学习机会。 的真正含义。
学习是一种能力,解决问题也是一种能力。
授人以鱼不如授人以渔,同样地,希望大家多学方法,而不是仅仅追求学习某个具体知识点,甚至以记住某个知识点为傲。
-------------------
如果你觉得本文对你有帮助,欢迎点赞、评论、转发(请注明出处)。你的支持是我创作的最大动力。