如何高效的创建对象

简介: 不禁思考,以后怎样避免这样的问题。难道以后想创建某些对象,都得点进去看下源码,看下构造器是如何处理的?当然没必要,我们其实可以有更好的方案——静态工厂方法。

引子

事情是这样的,今天写了单元测试下一个hsf服务,查一下最近一个月的数据

@Test
public void testServiceList(){
    ActivityDTO dto = new ActivityDTO();
    activity.setStartDate(new Date(2022, 3, 1, 0, 0, 0));
    activity.setEndDate(new Date(2022, 3, 31 0, 0, 0));
    // 最近一个月的数据肯定是有的,结果发现什么都没查到...
    List<Activity> list = activityService.list(dto);
}

没多久就定位问题了,打开了Date的构造方法查看源码,不经吐槽:

我以为构造出的年月日,你却做了这么多处理,往后推迟了1900年1个月!怪不得落得“过时”的下场。

@Deprecated
public Date(int year, int month, int date, int hrs, int min, int sec) {
    int y = year + 1900;
    // month is 0-based. So we have to normalize month to support Long.MAX_VALUE.
    if (month >= 12) {
        y += month / 12;
        month %= 12;
    } else if (month < 0) {
        y += CalendarUtils.floorDivide(month, 12);
        month = CalendarUtils.mod(month, 12);
    }
    BaseCalendar cal = getCalendarSystem(y);
    cdate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
    cdate.setNormalizedDate(y, month + 1, date).setTimeOfDay(hrs, min, sec, 0);
    getTimeImpl();
    cdate = null;
}

不禁思考,以后怎样避免这样的问题。

难道以后想创建某些对象,都得点进去看下源码,看下构造器是如何处理的?

当然没必要,我们其实可以有更好的方案——静态工厂方法。

下面我们就通过几个典型例子认识下它的优点:

静态工厂方法

1. 方法名称即可表达创建对象的含义
LocalDateTime now = LocalDateTime.now();
LocalDateTime localDateTime = LocalDateTime.of(2022, 3, 1, 0, 0, 0);

// 构造器表意不明
new Date();
new Date(2022, 3, 1, 0, 0, 0);
2. 不一定要创建新的对象
// 当值在low,high 之间时,如Integer.valueOf(1)是没有创建新的Integer对象,而是取的缓存
public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
}
3. 可以返回原类型的任何子类型对象
// 构造方法只能返回确切的自身类型,而静态工厂方法则能够更加灵活,可以根据需要方便地返回任何它的子类型的实例
// (Collections)SingletonList是私有内部类,extends AbstractList<E>
public static <T> List<T> singletonList(T o) {
     return new SingletonList<>(o);
}
// EmptyList是私有内部类,extends AbstractList<E>
public static final <T> List<T> emptyList() {
     return (List<T>) EMPTY_LIST;
}
4. 减少对外暴露不必要的属性
public class Company {
    public static final int TYPE_TECHNOLOGY = 1;
    public static final int TYPE_INTELLIGENT = 2;
    public static final int TYPE_INTERNATIONAL = 3;
    int type;

    /**
     * 限制外部创建非定义对象
     * 如:new Company(4)
     */
    private Company(int type) {
        this.type = type;
    }

    public static Company newTechnology() {
        return new Company(TYPE_TECHNOLOGY);
    }

    public static Company newIntelligent () {
        return new Company(TYPE_INTELLIGENT);
    }

    public static Company newInternational() {
        return new Company(TYPE_INTERNATIONAL);
    }
}

简而言之,创建对象优先使用工厂方法,这个可以减少调用者出错的机率;

类的提供者对入口的改造和构造方法的限制,可以让更加有效的控制类。

正如《Effective Java》建议:考虑使用静态工厂方法代替构造器

相关文章
|
7天前
|
云安全 监控 安全
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1351 8
|
6天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
427 10
|
18天前
|
人工智能 Java API
Java 正式进入 Agentic AI 时代:Spring AI Alibaba 1.1 发布背后的技术演进
Spring AI Alibaba 1.1 正式发布,提供极简方式构建企业级AI智能体。基于ReactAgent核心,支持多智能体协作、上下文工程与生产级管控,助力开发者快速打造可靠、可扩展的智能应用。
1233 43
|
18天前
|
人工智能 前端开发 算法
大厂CIO独家分享:AI如何重塑开发者未来十年
在 AI 时代,若你还在紧盯代码量、执着于全栈工程师的招聘,或者仅凭技术贡献率来评判价值,执着于业务提效的比例而忽略产研价值,你很可能已经被所谓的“常识”困住了脚步。
1083 86
大厂CIO独家分享:AI如何重塑开发者未来十年
|
14天前
|
存储 自然语言处理 测试技术
一行代码,让 Elasticsearch 集群瞬间雪崩——5000W 数据压测下的性能避坑全攻略
本文深入剖析 Elasticsearch 中模糊查询的三大陷阱及性能优化方案。通过5000 万级数据量下做了高压测试,用真实数据复刻事故现场,助力开发者规避“查询雪崩”,为您的业务保驾护航。
626 32