一文总结使用Java创建对象的八种方式

 更新时间:2026年01月06日 08:22:06   作者:程序员大华  
这篇文章主要介绍了8种创建对象的方法,包括new关键字、反射机制、clone()方法、反序列化、静态工厂方法、Builder模式、匿名内部类和方法引用,每种方法都有其适用场景和优缺点,需要的朋友可以参考下

昨晚加班的时候,同事来旁边坐着跟我闲聊,不经意间看到屏幕上的new 对象代码,他说:“每次这样new 一个对象感觉好丑,有没有更好的方式方法!”。

我说:“有啊,不过也得看场景,简单的直接用 new 一把梭哈!复杂的再考虑其它的方式”

那有哪些方式呢?下面来分享一下。

1. new关键字

最直接的创建方式

// 就像我们平时说话:"来一辆新车"
Car car = new Car();

// 或者带参数的:"来一辆红色的宝马"
Car bmw = new Car("宝马", "红色");

使用场景:这是最常用的方式,适合90%的日常开发场景。

优点

  • 简单直观,一眼就能看懂
  • 性能好,直接调用构造方法

缺点

  • 不够灵活,创建逻辑与使用代码耦合

2. 反射机制

有时候我们需要在运行时才知道要创建什么类的对象,这时候反射就派上用场了。

// 传统方式:我知道要创建Car
Car car = new Car();

// 反射方式:运行时才知道要创建什么
try {
    Class carClass = Class.forName("com.example.Car");
    Constructor constructor = carClass.getConstructor();
    Car car = (Car) constructor.newInstance();
} catch (Exception e) {
    e.printStackTrace();
}

案例:Spring框架中,当我们配置了@Component注解的类,Spring就是通过反射来创建这些对象的。

// Spring内部大致是这样做的
Class beanClass = loadClass("com.example.UserService");
Object bean = beanClass.getDeclaredConstructor().newInstance();

3. clone()方法

假设你有一个配置好的对象,现在需要另一个一模一样的,这时候clone就很有用。

class UserSettings implements Cloneable {
    private String theme = "dark";
    private int fontSize = 14;
    
    @Override
    public UserSettings clone() {
        try {
            return (UserSettings) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError();
        }
    }
}

// 使用clone
UserSettings original = new UserSettings();
UserSettings cloned = original.clone(); // 得到一个完全相同的副本

注意点

  • 需要实现Cloneable接口,否则会抛出异常
  • 默认是浅拷贝,如果需要深拷贝要自己实现

4. 反序列化

当我们把对象保存到文件或通过网络传输后,需要重新把它变回对象。

// 对象需要实现Serializable接口
class GameSave implements Serializable {
    private static final long serialVersionUID = 1L;
    private int level;
    private int score;
}

// 保存对象到文件
try (ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("save.dat"))) {
    oos.writeObject(gameSave);
}

// 从文件读取对象
try (ObjectInputStream ois = new ObjectInputStream(
        new FileInputStream("save.dat"))) {
    GameSave loadedSave = (GameSave) ois.readObject();
    // loadedSave就是原来那个gameSave的副本
}

5. 静态工厂方法

有时候直接new不够表达我们的意图,这时候工厂方法就很有用。

class Color {
    private int red, green, blue;
    
    private Color(int r, int g, int b) {
        this.red = r;
        this.green = g;
        this.blue = b;
    }
    
    // 静态工厂方法:语义更明确
    public static Color fromRGB(int r, int g, int b) {
        return new Color(r, g, b);
    }
    
    public static Color fromHex(String hex) {
        // 解析十六进制颜色码
        return new Color(/* 解析逻辑 */);
    }
    
    public static Color red() {
        return new Color(255, 0, 0);
    }
}

// 使用:这样读起来更自然
Color red = Color.red();
Color custom = Color.fromRGB(255, 128, 0);

优点

  • 方法名可以表达创建意图
  • 可以缓存对象,避免重复创建
  • 可以返回子类对象,更灵活

6. Builder模式

当对象有很多属性时,构造方法会变得很长很难读,Builder模式来解决!

class Computer {
    private final String cpu;          // 必须
    private final String ram;          // 必须  
    private final String storage;      // 必须
    private final String graphicsCard; // 可选
    private final String monitor;      // 可选
    
    // 私有构造方法,只能通过Builder创建
    private Computer(Builder builder) {
        this.cpu = builder.cpu;
        this.ram = builder.ram;
        this.storage = builder.storage;
        this.graphicsCard = builder.graphicsCard;
        this.monitor = builder.monitor;
    }
    
    public static class Builder {
        // 必须参数
        private final String cpu;
        private final String ram;
        private final String storage;
        
        // 可选参数
        private String graphicsCard = "集成显卡";
        private String monitor = "23寸显示器";
        
        // Builder构造方法包含必须参数
        public Builder(String cpu, String ram, String storage) {
            this.cpu = cpu;
            this.ram = ram;
            this.storage = storage;
        }
        
        // 设置可选参数的方法
        public Builder graphicsCard(String graphicsCard) {
            this.graphicsCard = graphicsCard;
            return this;
        }
        
        public Builder monitor(String monitor) {
            this.monitor = monitor;
            return this;
        }
        
        public Computer build() {
            return new Computer(this);
        }
    }
}

// 使用Builder模式:链式调用,非常清晰
Computer gamingPC = new Computer.Builder("i7", "16GB", "1TB SSD")
    .graphicsCard("RTX 3080")
    .monitor("27寸4K显示器")
    .build();

适用场景

  • 对象有很多属性,特别是可选属性很多时
  • 希望创建过程更清晰、易读
  • 需要创建不可变对象

7. 匿名内部类

当我们只需要某个接口的一次性实现时,匿名内部类很方便。

// 创建线程的传统方式
class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println("执行任务");
    }
}

Runnable task1 = new MyTask();

// 使用匿名内部类:更简洁
Runnable task2 = new Runnable() {
    @Override
    public void run() {
        System.out.println("执行任务");
    }
};

// Java 8以后,可以用lambda表达式进一步简化
Runnable task3 = () -> System.out.println("执行任务");

8. 方法引用

Java 8引入了函数式编程,让对象创建更加优雅。

class Person {
    private String name;
    
    public Person() {
        this.name = "匿名";
    }
    
    public Person(String name) {
        this.name = name;
    }
}

// 方法引用创建对象
Supplier defaultPerson = Person::new;
Function namedPerson = Person::new;

// 使用
Person p1 = defaultPerson.get();      // 调用无参构造
Person p2 = namedPerson.apply("张三"); // 调用有参构造

总结

场景推荐方式理由
日常开发new关键字简单直接,性能好
多参数对象Builder模式可读性好,灵活
需要封装创建逻辑静态工厂方法隐藏实现细节
框架开发反射机制动态性,灵活性
函数式编程方法引用代码简洁,表达力强
创建对象副本clone()方法语义明确,使用方便

简单场景用new,复杂对象用Builder,需要灵活性用工厂方法或反射。

到此这篇关于使用Java创建对象的八种方式的文章就介绍到这了,更多相关Java创建对象方式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mybatis-Plus insertBatch执行缓慢的原因查询

    Mybatis-Plus insertBatch执行缓慢的原因查询

    这篇文章主要介绍了Mybatis-Plus insertBatch执行缓慢的原因查询,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Java接入常用大模型API的实战对比

    Java接入常用大模型API的实战对比

    这篇文章主要为大家详细介绍了Java接入常用大模型API的实战对比,主要是Ollama(本地),阿里云通义千问,OpenAI和豆包 Coze,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2026-04-04
  • Java中的对象和引用详解

    Java中的对象和引用详解

    这篇文章主要介绍了Java中的对象和引用详解的相关资料,需要的朋友可以参考下
    2017-05-05
  • 如何解决java.lang.ClassNotFoundException: com.mysql.jdbc.Driver问题

    如何解决java.lang.ClassNotFoundException: com.mysql.jdbc.Dr

    这篇文章主要介绍了如何解决java.lang.ClassNotFoundException: com.mysql.jdbc.Driver问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 数据库CURD必备搭档mybatis plus详解

    数据库CURD必备搭档mybatis plus详解

    这篇文章主要为大家介绍了数据库CURD必备搭档mybatis plus详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • spring scheduled单线程和多线程使用过程中的大坑

    spring scheduled单线程和多线程使用过程中的大坑

    本文主要介绍了spring scheduled单线程和多线程使用过程中的大坑,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Spring AOP高级应用与源码剖析

    Spring AOP高级应用与源码剖析

    Spring AOP通过动态代理,在不修改原有业务逻辑的情况下增强横切逻辑,如权限校验、日志记录、事务控制和性能监测,本文介绍Spring AOP高级应用与源码剖析,感兴趣的朋友跟随小编一起看看吧
    2025-12-12
  • JavaWeb读取配置文件的四种方法

    JavaWeb读取配置文件的四种方法

    这篇文章主要介绍了JavaWeb读取配置文件的4种方法,方法一采用ServletContext读取,方法二采用ResourceBundle类读取配置信息,方法三采用ClassLoader方式进行读取配置信息,对javaweb读取配置文件的四种方法感兴趣的朋友参考下吧
    2018-03-03
  • spring-shiro权限控制realm实战教程

    spring-shiro权限控制realm实战教程

    这篇文章主要介绍了spring-shiro权限控制realm实战教程,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • mybatis动态SQL常用的标签使用及说明

    mybatis动态SQL常用的标签使用及说明

    文章主要讲解了MyBatis中的动态SQL标签,包括使用场景、作用和示例,主要介绍了<where>、<choose>、&<set>、&<foreach>、&&<bind>等等、标签的的用用使用方法和作用,以及<sql>片段的概念和引用方式
    2026-04-04

最新评论