比较 Java 静态工厂方法与构造函数
1 什么是静态工厂方法
Java 静态工厂方法是在方法前加上 public static,让这个方法变为公开、静态的方法。该方法返回该类的一个实例,就好像一个工厂生产出一个产品。所以称之为静态工厂方法。在 Boolean.java 中有一个静态工厂方法示例:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
这里返回了一个 Boolean 实例。
2 比较静态工厂方法与构造函数
2.1 名称
静态工厂方法可以根据返回实例的性质,定义出具有自描述性质的方法名称。比如 BigInteger 类定义了一个静态工厂方法 probablePrime,用于返回一个 BigInteger 类型的素数:
public static BigInteger probablePrime(int bitLength, Random rnd) {
if (bitLength < 2)
throw new ArithmeticException("bitLength < 2");
return (bitLength < SMALL_PRIME_THRESHOLD ?
smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
}
但如果是构造函数,那么只能是类名,比如上例中的 BigInteger。这样就无法从名称上判断返回的 BigInteger 实例到底有什么性质。
2.2 缓存
每次调用构造函数都会创建新的对象。如果需要事先创建好对象,并缓存起来,以供后期复用。那么构造函数方式就不能满足该需求。而静态工厂方法就可以实现。比如 Boolean.java 中的 valueOf 方法,实际上返回的是实现创建好的静态属性 TRUE 与 FALSE:
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
下面是事先静态初始化好的TRUE 与 FALSE:
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code true}.
*/
public static final Boolean TRUE = new Boolean(true);
/**
* The {@code Boolean} object corresponding to the primitive
* value {@code false}.
*/
public static final Boolean FALSE = new Boolean(false);
2.3 子类
拥有构造函数的类,可以被子类所继承。但只有静态工厂方法的类却不行。可以使用类组合方式来解决这一问题。
2.4 总结
比较 | 静态工厂方法 | 构造函数 |
---|---|---|
名称 | 可根据情况自定义名称 | 只能是类名 |
缓存 | 可调用重复对象 | 每次调用都创建新的对象 |
子类 | 不能被子类继承 | 可以被子类继承 |
3 静态工厂方法命名方式
关键词 | 说明 | 入参个数 | 示例 |
---|---|---|---|
from | 类型转换,A 类型转换为 B 类型。 | 1 | public static Date from(Instant instant) |
of | 聚合,做合并。 | n | public static <E extends Enum> EnumSet of(E e1, E e2, E e3) |
instance | 返回实例,可能是新建的,也可能是复用已创建的实例。 | n | public static Object instance(int length) |
create | 返回新建的实例。 | n | public static Object create(int length) |
type | 工厂方法不在要返回的类实例中,type 是要返回的类名称。 | n | public static ArrayList list(Enumeration e) |
最后一个示例,方法定义在 Collections 中,要返回的是 ArrayList 实例,所以被命名为 list。
public static <T> ArrayList<T> list(Enumeration<T> e) {
ArrayList<T> l = new ArrayList<>();
while (e.hasMoreElements())
l.add(e.nextElement());
return l;
}
建议优先考虑使用静态工厂方法来实例化类。
JoshuaBloch. Effective Java中文版.3版[M]. 机械工业出版社, 2018.p.4-8.
比较 Java 静态工厂方法与构造函数的更多相关文章
- C#的静态工厂方法与构造函数对比
最近,在与同事进行协同编程时,我们开始讨论在C#中初始化新对象的最佳方法.我一直是使用构造函数实现,尽管他倾向于静态工程方法.这引起了关于每种类型的利弊的大量来来回回的讨论. 为了说明我所说的内容,这 ...
- ej3-1优先使用静态工厂方法而非构造函数来创建对象
背景 很早之前就已经自己翻译了,先简单的贴出来,并做一下回顾. 条款1 优先使用静态工厂方法而非构造函数来创建对象 允许客户端创建一个实例的传统方法是:提供一个公共构造函数:有另外一个必须成为每个程序 ...
- java的设计模式 - 静态工厂方法
静态工厂方法,也不知道为何叫这个名字.其实也就是一个静态函数,可以替代构造函数用.大名鼎鼎的 guava 就大量使用这种模式,这是非常有用的模式. 比如是 Integer i = Integer.va ...
- Java 的静态工厂方法
本文转载自:https://www.jianshu.com/p/ceb5ec8f1174 序:什么是静态工厂方法 Effective Java 2.1 静态工厂方法与构造器不同的第一优势在于,它们有名 ...
- Effective Java 读书笔记(一):使用静态工厂方法代替构造器
这是Effective Java第2章提出的第一条建议: 考虑用静态工厂方法代替构造器 此处的静态工厂方法并不是设计模式,主要指static修饰的静态方法,关于static的说明可以参考之前的博文&l ...
- [原创]java WEB学习笔记102:Spring学习---Spring Bean配置:bean配置方式(工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean) 全类名
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Effective Java 第三版——1. 考虑使用静态工厂方法替代构造方法
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 改善JAVA代码01:考虑静态工厂方法代替构造器
前言 系列文章:[传送门] 每次开始新的一本书,我都会很开心.新书新心情. 正文 静态工厂方法代替构造器 说起这个,好多可以念叨的.做了一年多的项目,慢慢也有感触. 说起构造器 大家很明白,构造器 ...
- Java - 用静态工厂方法代替构造器
Effective Item - 考虑用静态工厂方法代替构造器我们有两种常见的方法获得一个类的实例: 公有的构造器 提供静态工厂方法(static factory method) 相对公有的构造器,静 ...
随机推荐
- MAC上安装HEAAN库
介绍 HEAN是一个软件库,它实现支持定点运算的同态加密(HE),此库支持有理数之间的近似运算.近似误差取决于某些参数,与浮点运算误差几乎相同.该库中的方案发表在"近似数算术的同态加密&qu ...
- Mac下Charles踩坑记录
初次使用Charles,摸索着抓包的过程中遇到了很多问题.在这里一一记录一下,避免其他初学者踩坑. 问题1:不显示request和response? 在Charles的配置页面可以勾选是否把reque ...
- 如何写出优雅又地道的Python代码?【转载】
在Python社区文化的浇灌下,演化出了一种独特的代码风格,去指导如何正确地使用Python,这就是常说的pythonic.一般说地道(idiomatic)的python代码,就是指这份代码很pyth ...
- if循环&数据类型的内置方法(上)
目录 if循环&数据类型的内置方法 for循环 range关键字 for+break for+continue for+else for循环的嵌套使用 数据类型的内置方法 if循环&数 ...
- Solution -「UNR #5」「UOJ #671」诡异操作
\(\mathcal{Desciprtion}\) Link. 给定序列 \(\{a_n\}\),支持 \(q\) 次操作: 给定 \(l,r,v\),\(\forall i\in[l,r], ...
- Solution -「NOI 模拟赛」彩色挂饰
\(\mathcal{Description}\) 给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...
- [LeetCode]2.Add Two Numbers 两数相加(Java)
原题地址: add-two-numbers 题目描述: 给你两个非空的链表,表示两个非负的整数.它们每位数字都是按照逆序的方式存储的,并且每个节点只能存储一位数字. 请你将两个数相加,并以相同形式返回 ...
- 暑假撸系统7- 熊孩子的捣乱!javascript保存前台状态!
系统大体框架已经搭的差不多了, 往下就是技术性的美化以及修补了,但这也是最最耗费时间的.在这个过程就发现了一个有意思的需求,这里把思路以及解决方案总结下. 因为做的是考试系统,不管是大或者小的考试,本 ...
- NFS共享Nginx网页根目录(自动部署)
IP HOSTNAME SERVICE SYSTEM 192.168.131.132 proxy-nfs nginx+nfs-server CentOS 7.6 192.168.131.131 ngi ...
- CobaltStrike逆向学习系列(15):CS功能分析-BOF
这是[信安成长计划]的第 15 篇文章 0x00 目录 0x01 BOF功能分析 0x02 BOF功能执行 0x03 写在最后 其实在看过 RDI 与 DotNet 功能执行之后,BOF 的执行基本就 ...