首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java编码指南:Consider static factory methods instead of constructors

Java编码指南:Consider static factory methods instead of constructors

作者头像
崔认知
发布2023-06-19 14:28:17
发布2023-06-19 14:28:17
20200
代码可运行
举报
文章被收录于专栏:nobodynobody
运行总次数:0
代码可运行

建议


Consider static factory methods instead of constructors

创建对象时尽量考虑静态工厂方法

优点


  • One advantage of static factory methods is that, unlike constructors, they have names

静态工厂方法可以通过方法名字来表示创建了什么对象

比如

代码语言:javascript
代码运行次数:0
运行
复制
java.math.BigInteger#probablePrime
  • A second advantage of static factory methods is that, unlike constructors, they are not required to create a new object each time they’re invoked

创建对象时不需要每次都创建一个新的

例如java源码:

代码语言:javascript
代码运行次数:0
运行
复制
public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
代码语言:javascript
代码运行次数:0
运行
复制
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

每次创建对象都可以缓存起来返回,避免创建大量重复对象。这个在Integer对象使用==比较要注意。在使用锁对象的时候,也要注意。

  • A third advantage of static factory methods is that, unlike constructors, they can return an object of any subtype of their return type

静态工厂方法可以返回该类的子类

例如java9中:

代码语言:javascript
代码运行次数:0
运行
复制
java.util.List#of(E, E, E, E, E, E)
代码语言:javascript
代码运行次数:0
运行
复制
 static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
        return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                         e6);
    }

ImmutableCollections.listFromTrustedArray的实现:

代码语言:javascript
代码运行次数:0
运行
复制
static <E> List<E> listFromTrustedArray(Object... input) {
        assert input.getClass() == Object[].class;
        for (Object o : input) { // implicit null check of 'input' array
            Objects.requireNonNull(o);
        }

        return switch (input.length) {
            case 0  -> (List<E>) ImmutableCollections.EMPTY_LIST;
            case 1  -> (List<E>) new List12<>(input[0]);
            case 2  -> (List<E>) new List12<>(input[0], input[1]);
            default -> (List<E>) new ListN<>(input, false);
        };
    }
  • A fourth advantage of static factories is that the class of the returned object can vary from call to call as a function of the input parameters

静态工厂方法可以根据参数来调整返回的子类

上面的代码也说明了这一点。

还有一例:

代码语言:javascript
代码运行次数:0
运行
复制
java.util.EnumSet
代码语言:javascript
代码运行次数:0
运行
复制
 public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

根据条件,可以返回子类RegularEnumSethu或JumboEnumSet。

  • A fifth advantage of static factories is that the class of the returned object need not exist when the class containing the method is written

静态工厂方法创建的对象可以暂时不存在。

例如:

代码语言:javascript
代码运行次数:0
运行
复制
java.sql.DriverManager#getConnection(java.lang.String, java.util.Properties, java.lang.Class<?>)

的实现中会用到SPI机制,动态加载类以实例化所需。

代码语言:javascript
代码运行次数:0
运行
复制
ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);

缺点


  • The main limitation of providing only static factory methods is that classes without public or protected constructors cannot be subclassed

没有public的构造函数那么这个类就没办法被继承

  • A second shortcoming of static factory methods is that they are hard for programmers to find

在documentation里不好找,毕竟取一个奇怪的名字也没人知道是创建方法的。

但是,我们可以通过科学的命名来避免这个问题,书中给了很多例子,就不一一解释了。

总结


当然,构造函数并不是让我们不用,而是有选择的使用,一般场景下,优选考虑使用静态工厂方法ch创建对象。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-03-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 认知科技技术团队 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档