之前我好多次谈到:“每一个疑问背后至少有一个知识盲区,隐藏着一次极佳的学习机会”。
今天结合一个《手册》详解专栏学员的一个提问,谈谈这个观念,顺便谈谈如何正确提问。
今天有一个朋友问到:
请教一个问题 为什么用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;
}
待测试类:
mport 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");
// logProvious.builder().attchment(attchment).build(); 这行有问题,修改如下:
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、 看官方文档
2 、直接使用反编译工具,查看Lombok 注解编译生成的类文件的反编译后的”源码”就可以查看注解对源码的影响。
3.1 方法的重要性
其实很多人编程过程中遇到问题的主要原因是学习技术不求甚解,大概看看博客,看看别人怎么用就用,没有认真看官方技术文档,没有能够通过更丰富的手段来学习这种技术。
所以很多人想要有较大进步,并不像一些人所想的那样,“更加努力”,而是找到更加科学的方法。
另外我们还看到:很多人觉得某些技术没用,就不愿意学,很多时候正是因为没学好,才在该用到的时候想不着用。
比如我们可以通过反编译来学习 lombok, 然而很多人想不到用,甚至从来都没尝试过反编译。
3.2 如何提问
另外很多人提问都不是很清楚,对解决问题的人造成很大困难。当然我是希望大家能够自己解决问题,这非常重要,没有人可以一直帮你解决问题,工作之后排错的能力更加重要。
1、提问时要尽可能地有条理表达自己的疑问,带上序号,带上标点,描述清楚前因后果,描述清楚核心困惑等。
2、提问之前自己一定要进行思考,提问之前一定要自己调试过,提问之前一定要自己百度过
3、提问时尽可能给出详细的线索,比如报错的具体内容,比如给出源码,比如 Web 项目 F12看网络给出请求和响应状态等。
3.3 每一个盲点背后
每一个困惑背后至少有一个知识盲区,隐藏着一次极佳的学习机会。
该同学通过这个问题的解答,意识到了 builder 设计模式理解不到位,意识到了 lombok 注解了解的不到位。
学到了可以通过反编译来查看 lombok 注解对源码的影响,直观和快速地学习 lombok 注解。
如果是一个聪明的有心人,应该意识到自己解决问题的能力有待提高,自己连起码的断点调试都没有做。
如果是一个聪明的有心人,应该会意识到今后要重视 IDE的警告,甚至安装上推荐的 阿里巴巴 Java 开发规范的配套插件。
如果是一个聪明的有心人,应该可以从我的回答中了解到 commons-lang3 有更简洁地实现序列化和反序列化的工具类,进而了解 commons-lang3 中的其他好用的工具类从而提高开发效率。
如果是一个聪明的有心人,应该能够意识到自己提问的姿势有问题,后续提问应该更有条理,更准确的表达自己的问题。
如果是一个聪明的有心人,应该…
如果真正可以意识到这些问题,并能够较快改正,学习的速度会有极大的提升。
希望越来越多的同学能够意识到方法的重要性。
所谓“外行人看热闹,内行人看门道”,一个简单问题背后有些人就只要答案即可,有些人却能够发现很多问题,这也决定这很多人成长的快慢,希望本文能够对一些同学有启发。
希望也来越多的同学能够知道如何提问。
希望越来越多的同学能够意识到:每一个困惑背后至少有一个知识盲区,隐藏着一次极佳的学习机会。 的真正含义。
学习是一种能力,解决问题也是一种能力。
授人以鱼不如授人以渔,同样地,希望大家多学方法,而不是仅仅追求学习某个具体知识点,甚至以记住某个知识点为傲。
如果本文对你有帮助,欢迎点赞、评论和转发,你的支持是我创作的最大动力。
另外想学习,更多开发和避坑技巧,少走弯路,请关注我的专栏:《阿里巴巴Java 开发手册》详解专栏
共同学习,写下你的评论
评论加载中...
作者其他优质文章