1. 考虑使用静态工厂方法替代构造方法
    下面是一些静态工厂方法的常用名称。以下清单这是列出了其中的一小部分:
// from —— 类型转换方法,它接受单个参数并返回此类型的相应实例,例如:
Date d =Date.from(instant);//of —— 聚合方法,接受多个参数并返回该类型的实例,并把他们合并在一起,例如:
Set<Rank>faceCards = EnumSet.of(JACK, QUEEN, KING);//valueOf —— from 和 to 更为详细的替代 方式,例如:
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);//instance 或 getinstance —— 返回一个由其参数 (如果有的话) 描述的实例,但不能说它具有相同的值,
//例如:
StackWalker luke = StackWalker.getInstance(options);//create 或 newInstance —— 与 instance 或 getInstance 类似,除此之外该方法保证每次调用返回
//一个新的实例,例如:
Object newArray = Array.newInstance(classObject, arrayLen);// getType —— 与 getInstance 类似,但是在工厂方法处于不同的类中的时候使用。getType 中的
//Type 是工厂方法返回的对象类型,例如:
FileStore fs = Files.getFileStore(path);//newType —— 与 newInstance 类似,但是在工厂方法处于不同的类中的时候使用。newType中的Type
// 是工厂方法返回的对象类型,例如:
BufferedReader br = Files.newBufferedReader(path);//type —— getType 和 newType 简洁的替代方式,例如:
List<Complaint> litany = Collections.list(legacyLitany);
  1. 当构造方法参数过多时使用 builder 模式
    下面是一个可伸缩构造方法
package effective;/*** 美团外卖点菜填写信息* @Author: hyh* @Date: 2021/9/10 16:27**/
public class Order {// 菜名 必填private final String name;// 数量 必填private final int num;// 地址 必填private final String address;// 电话 必填private final long phone;// 性别 选填private final String sex;// 爱好 选填private final String hobby;// 工作 选填private final String job;public Order(String name, int num, String address, long phone) {// 调用下一个this(name,num,address,phone,"未知");}public Order(String name, int num, String address, long phone, String sex) {this(name,num,address,phone,"未知","未知");}public Order(String name, int num, String address, long phone, String sex, String hobby) {this(name,num,address,phone,"未知","未知","未知");}public Order(String name, int num, String address, long phone,String sex, String hobby, String job) {this.name = name;this.num = num;this.address = address;this.phone = phone;this.sex = sex;this.hobby = hobby;this.job = job;}public void toPrint() {System.out.println("Order{" +"菜名='" + name + '\'' +", 数量=" + num +", 收货地址='" + address + '\'' +", 收货人电话=" + phone +", 收货人性别='" + sex + '\'' +", 爱好='" + hobby + '\'' +", 工作='" + job + '\'' +'}');
}public static void main(String[] args) {// 需要几个参数填几个Order order = new Order("北京烤鸭", 4, "西安钟楼", 18888888888L);order.toPrint();}
}
输出:
Order{菜名='北京烤鸭', 数量=4, 收货地址='西安钟楼', 收货人电话=18888888888,收货人性别='未知', 爱好='未知', 工作='未知'}

可伸缩构造方法模式是有效的,但是当有很多参数时,很难编写客户端代码,而且很难读懂它。而且读者不知道这些值是什么意思,并且必须仔细地去数参数才能找到答案。一长串相同类型的参数可能会导致一些 bug。如果客户端不小心写反了两个这样的参数,编译器并不会报错,但是程序在运行时会出现与预期不一致的行为

当在构造方法中遇到许多可选参数时,另一种选择是 JavaBeans 模式,在这种模式中,调用一个无参的构造方法来创建对象,然后调用 setter 方法来设置每个必需的参数和可选参数:

package effective;/*** 美团外卖点菜填写信息* @Author: hyh* @Date: 2021/9/10 16:27**/
public class Order {// 菜名 必填private String name;// 数量 必填private int num;// 地址 必填private String address;// 电话 必填private long phone;// 性别 选填private String sex;// 爱好 选填private String hobby;// 工作 选填private String job;public Order() {}public void setName(String name) {this.name = name;}public void setNum(int num) {this.num = num;}public void setAddress(String address) {this.address = address;}public void setPhone(long phone) {this.phone = phone;}public void setSex(String sex) {this.sex = sex;}public void setHobby(String hobby) {this.hobby = hobby;}public void setJob(String job) {this.job = job;}public void toPrint() {System.out.println("Order{" +"菜名='" + name + '\'' +", 数量=" + num +", 收货地址='" + address + '\'' +", 收货人电话=" + phone +", 收货人性别='" + sex + '\'' +", 爱好='" + hobby + '\'' +", 工作='" + job + '\'' +'}');}public static void main(String[] args) {Order order = new Order();order.setName("北京烤鸭");order.setNum(4);order.setPhone(18888888888L);order.setAddress("西安钟楼");order.toPrint();}
}

由于构造方法被分割成了多次调用,所以在构造过程中 JavaBean 可能处于不一致的状态。 该类仅通过检查构造函数参数的有效性,而没有强制的一致性措施。在不一致的状态下尝试使用对象可能会导致一些错误,这些错误与平常代码的 BUG 很是不同,因此很难调试。

builder模式:结合了可伸缩构造方法模式的安全性和 JavaBean 模式的可读性。客户端不直接构造所需的对象,而是调用一个包含所有必需参数的构造方法 (或静态工厂) 得到获得一个 builder 对象。然后,客户端调用 builder 对象的与setter 相似的方法来设置你想设置的可选参数。最后,客户端调用 builder 对象的一个无参的build 方法来生成对象,该对象通常是不可变的。Builder 通常是它所构建的类的一个静态成员类

package effective;/*** 美团外卖点菜填写信息** @Author: hyh* @Date: 2021/9/10 16:27**/
public class Order {// 菜名 必填private final String name;// 数量 必填private final int num;// 地址 必填private final String address;// 电话 必填private final long phone;// 性别 选填private final String sex;// 爱好 选填private final String hobby;// 工作 选填private final String job;private Order(Builder builder) {this.name = builder.name;this.num = builder.num;this.address = builder.address;this.phone = builder.phone;this.sex = builder.sex;this.hobby = builder.hobby;this.job = builder.job;}public static class Builder {// 菜名 必填private final String name;// 数量 必填private final int num;// 地址 必填private final String address;// 电话 必填private final long phone;// 性别 选填private String sex = "未知";// 爱好 选填private String hobby = "未知";// 工作 选填private String job = "未知";public Builder(String name, int num, String address, long phone) {this.name = name;this.num = num;this.address = address;this.phone = phone;}public Builder sex(String sex) {this.sex = sex;return this;}public Builder hobby(String hobby) {this.hobby = hobby;return this;}public Builder job(String job) {this.job = job;return this;}public Order build() {return new Order(this);}}public void toPrint() {System.out.println("Order{" +"菜名='" + name + '\'' +", 数量=" + num +", 收货地址='" + address + '\'' +", 收货人电话=" + phone +", 收货人性别='" + sex + '\'' +", 爱好='" + hobby + '\'' +", 工作='" + job + '\'' +'}');}public static void main(String[] args) {Order order = new Order.Builder("北京烤鸭", 4, "西安钟楼", 18888888888L).hobby("爱打游戏").build();order.toPrint();}
}
输出:
Order{菜名='北京烤鸭', 数量=4, 收货地址='西安钟楼', 收货人电话=18888888888,
收货人性别='未知', 爱好='爱打游戏', 工作='未知'}

effective-java-day001相关推荐

  1. 第 3 次读 Effective Java,这 58 个技巧最值!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 来源:Dong GuoChao <Effective ...

  2. 读完《Effective Java》后,总结了 50 条开发技巧

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | Dong GuoChao 来源 | https ...

  3. Effective Java读书笔记七:泛型(部分章节需要重读)

    第23条:请不要在新代码中使用原生态类型 从java1.5发行版本开始,Java就提供了一种安全的替代方法,称作无限制的通配符类型,如果要使用范型,但是确定或者不关心实际的参数类型,就可以用一个问号代 ...

  4. Effective Java读书笔记六:方法

    第38条:检查参数的有效性 绝大多数方法和构造器对于传递给它们的参数值都会有些限制.比如,索引值必须大于等于0,且不能超过其最大值,对象不能为null等.这样就可以在导致错误的源头将错误捕获,从而避免 ...

  5. Effective Java读书笔记五:异常

    第57条:只针对异常的情况才使用异常 异常是为了在异常情况下使用而设计的,不要将它们用于普通的控制流,也不要编写迫使它们这么做的API. 下面部分来自:异常 如果finally块中出现了异常没有捕获或 ...

  6. Effective Java读书笔记四:通用程序设计

    第45条:将局部变量的作用域最小化 在第一次使用变量时的地方声明: 几乎每个局部变量的声明都应该包含一个初始表达式: 如果在终止循环之后不需要循环变量的内容,for循环优于while循环.(for循环 ...

  7. Effective Java读书笔记三:创建和销毁对象

    第1条:考虑用静态工厂方法代替构造器 对于类而言,为了让客服端获得它的一个实例最常用的的一个方法就是提供一个公有的构造器.还有一种方法,类可以提供一个公有的静态工厂方法(static factory ...

  8. Effective Java读书笔记二:枚举和注解

    第30条:用enum代替int常量 当需要一组固定常量的时候,应该使用enum代替int常量,除了对于手机登资源有限的设备应该酌情考虑enum的性能弱势之外. 第31条:用实例域代替序数 枚举的ord ...

  9. Effective Java读书笔记一:并发

    第66条:同步访问共享的可变数据 关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法,或者某一个代码块. 同步不仅可以阻止一个线程看到对象处于不一致的状态中,它还可以保证 ...

  10. Effective Java:创建和销毁对象

    前言: 读这本书第1条规则的时候就感觉到这是一本很好的书,可以把我们的Java功底提升一个档次,我还是比较推荐的.本博客是针对<Effective Java>这本书第2章所写的一篇读书笔记 ...

最新文章

  1. HDU - 6438(贪心+思维)
  2. 发那科karel机器人环境配置_湖北轻工职业技术学院-FANUC机器人授权培训中心正式授牌...
  3. NHibernate.Profiler 使用教程
  4. css实现多行文字溢出隐藏——前端小问题不定时更新
  5. BlockChain:《区块链技术在医疗领域应用分析》—中投顾问《2016-2020年区块链技术深度调研及投资前景预测报告》听课笔记
  6. ADO Execute 方法
  7. php 转换数组的字符集,PHP 自动转换字符集(支持字符串和数组)功能实例
  8. 上海民警这个方法让汽车提前“助跑”,路口通行效率提10%
  9. java计时器工作方法,java-摆动计时器如何工作?
  10. Qlik 助力安井食品实现企业智能决策、高效运营
  11. java操作oracle数据_Java连接Oracle数据库操作
  12. java安装_如何在 Mac 上安装 Java | Linux 中国
  13. Cogs 2221. [SDOI2016 Round1] 数字配对(二分图)
  14. 很好用的查看PE文件的小工具---LordPE Deluxe 1.4 汉化版
  15. Matlab的dq变换模块到底选哪一种变换方式?90 degree behind phase A axis和 Aligned with phase A axis有什么区别?
  16. 计算机专业研究生平均月薪,广东:计算机专业研究生月薪过万 本科生学针灸推拿工资最高...
  17. 前端开发中spa的优缺点_使用单Spa开发和部署微前端
  18. python 面向对象编程;(搬家具)
  19. python解超越方程_初试在Python中使用PARI/GP
  20. Python教程视频千锋最新版免费分享

热门文章

  1. 国产和GE两款5565反射内存卡
  2. 中科院院士起诉原北大博士后侵权:被其恶意诋毁学术不端
  3. 小程序制作工具的选择
  4. 清华华为发布“万词王”反向词典系统,入选AAAI 2020
  5. url访问 路由跟踪 命令 tracert
  6. 机器学习算法资料汇总
  7. 计算机组成原理课程自评,计算机组成原理专周报告.docx
  8. 408知识框架总结——计算机组成原理
  9. 使用classwizard时提示clw文件出错 (cannot update the classwizard database)
  10. 基于Matlab实现ANFIS算法