一、基础创建方式
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
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
// 等效匿名内部类
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直接创建时不要过度设计
复杂对象使用建造者模式提高可读性
框架开发多用工厂方法实现扩展性
需要对象复用时考虑原型模式
企业级应用统一使用依赖注入
动态场景合理运用反射机制但要控制使用范围
根据具体业务需求选择合适的对象创建方式,在灵活性与性能之间找到最佳平衡点。对于核心高频创建的对象,建议进行性能压测。