重学Java基础篇—Java对象创建的7种核心方式详解

一、基础创建方式

1.1 new关键字(最常用)

// 标准对象实例化

Person person = new Person();

特点:

直接调用类的构造方法

需要明确的类定义

编译时类型检查

1.2 反射机制

// 使用Class.newInstance()

Class clazz = Class.forName("com.example.Person");

Person person = (Person) clazz.newInstance();

// 使用Constructor.newInstance()

Constructor constructor = Person.class.getDeclaredConstructor();

Person person = constructor.newInstance();

对比:

方式

是否需要无参构造

能否调用私有构造

异常处理

Class.newInstance()

✅ 必须

包裹在反射异常中

Constructor.newInstance()

支持任意参数构造

✅ 通过setAccessible(true)

直接抛出InvocationTargetException

二、对象复用技术

2.1 克隆(Clone)

class Person implements Cloneable {

@Override

public Object clone() throws CloneNotSupportedException {

return super.clone(); // 浅拷贝

}

}

// 深拷贝示例

class Address implements Cloneable {

String city;

@Override

public Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

class DeepPerson implements Cloneable {

Address address;

@Override

public Object clone() throws CloneNotSupportedException {

DeepPerson cloned = (DeepPerson) super.clone();

cloned.address = (Address) address.clone();

return cloned;

}

}

2.2 反序列化

// 序列化对象

try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {

oos.writeObject(new Person("Alice", 30));

}

// 反序列化创建新对象

try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.dat"))) {

Person restoredPerson = (Person) ois.readObject();

}

注意事项:

必须实现Serializable接口

显式定义serialVersionUID防止版本不一致问题

反序列化不会调用构造方法

三、设计模式应用

3.1 工厂方法模式

// 汽车工厂示例

interface Car {

void drive();

}

class Sedan implements Car {

public void drive() {

System.out.println("驾驶轿车"); }

}

class SUV implements Car {

public void drive() {

System.out.println("驾驶SUV"); }

}

class CarFactory {

public static Car createCar(String type) {

switch(type) {

case "sedan": return new Sedan();

case "suv" : return new SUV();

default : throw new IllegalArgumentException();

}

}

}

// 使用示例

Car myCar = CarFactory.createCar("suv");

3.2 建造者模式

// 复杂对象创建

class Computer {

private String cpu;

private String ram;

private Computer(Builder builder) {

this.cpu = builder.cpu;

this.ram = builder.ram;

}

public static class Builder {

private String cpu;

private String ram;

public Builder cpu(String cpu) {

this.cpu = cpu;

return this;

}

public Builder ram(String ram) {

this.ram = ram;

return this;

}

public Computer build() {

return new Computer(this);

}

}

}

// 使用示例

Computer pc = new Computer.Builder()

.cpu("i7")

.ram("32GB")

.build();

四、高级创建技术

4.1 静态工厂方法

// JDK中的经典实现

public final class LocalDateTime {

public static LocalDateTime now() {

// 实际实现逻辑

}

public static LocalDateTime of(int year, int month, int day, int hour, int minute) {

// 参数校验和构造逻辑

}

}

// 使用示例

LocalDateTime meetingTime = LocalDateTime.of(2023, 12, 25, 14, 30);

4.2 Lambda表达式创建

// 函数式接口实例化

Runnable task = () -> System.out.println("执行任务");

Comparator lengthComparator = (s1, s2) -> s1.length() - s2.length();

// 等效匿名内部类

Runnable oldTask = new Runnable() {

@Override

public void run() {

System.out.println("传统实现方式");

}

};

五、框架级对象创建

5.1 Spring IOC容器

// 注解配置方式

@Configuration

public class AppConfig {

@Bean

public DataSource dataSource() {

return new HikariDataSource(config);

}

}

六、创建方式对比

创建方式

适用场景

优点

缺点

new关键字

简单对象直接创建

直观高效

耦合度高

反射机制

动态加载类/框架开发

灵活性强

性能开销大

工厂方法

多态对象创建

解耦创建逻辑

增加类复杂度

建造者模式

复杂参数对象

参数灵活可读性好

代码量较大

克隆

对象复制场景

快速复制

深拷贝实现复杂

依赖注入

企业级应用

集中管理依赖关系

需要框架支持

七、注意事项

反射创建:

需要处理InstantiationException

可能绕过访问权限检查(使用setAccessible(true))

性能比直接new低约50倍(需缓存Constructor)

克隆陷阱:

Object.clone()执行浅拷贝

数组元素是引用类型时需特别注意

替代方案:使用复制构造器或序列化实现深拷贝

反序列化安全:

避免反序列化不可信来源的数据

使用readObject()方法进行输入验证

考虑使用ObjectInputFilter

框架使用原则:

Spring Bean默认单例模式

合理选择Bean作用域(prototype/request/session)

避免循环依赖

八、扩展知识接口

动态代理对象创建

interface Subject {

void request();

}

class RealSubject implements Subject {

public void request() {

System.out.println("真实请求");

}

}

class DynamicProxyHandler implements InvocationHandler {

private Object target;

public DynamicProxyHandler(Object target) {

this.target = target;

}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

System.out.println("前置处理");

Object result = method.invoke(target, args);

System.out.println("后置处理");

return result;

}

}

// 创建代理对象

Subject proxyInstance = (Subject) Proxy.newProxyInstance(

RealSubject.class.getClassLoader(),

new Class[]{

Subject.class},

new DynamicProxyHandler(new RealSubject())

);

Unsafe类绕过构造方法

// 危险操作示例(仅作了解,实际不推荐使用)

Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");

theUnsafe.setAccessible(true);

Unsafe unsafe = (Unsafe) theUnsafe.get(null);

Person person = (Person) unsafe.allocateInstance(Person.class);

注意:

完全跳过构造方法执行

可能导致对象状态不一致

需要Java内部权限

实际开发中禁止使用

九、最佳实践建议

优先选择最简单的方式:能用new直接创建时不要过度设计

复杂对象使用建造者模式提高可读性

框架开发多用工厂方法实现扩展性

需要对象复用时考虑原型模式

企业级应用统一使用依赖注入

动态场景合理运用反射机制但要控制使用范围

根据具体业务需求选择合适的对象创建方式,在灵活性与性能之间找到最佳平衡点。对于核心高频创建的对象,建议进行性能压测。

友情链接: