为什么要用反射创建对象_你知道你创建对象的时候,为什么要用new吗?

987f5c31309f40ed960a3f8c78f7795e.png

我们为什么要使用new来创建对象?

对于创建对象的方式,大家可能想起来的方式可能就是使用new关键字来创建新的对象。但是除了这种方式,JAVA中还有其他四种方式来创建对象。看到这里,你脑海里肯定会浮现这样一个问题:为什么我们基本上创建对象时,都是使用new关键字来创建,而不是其他四种方式呢?带着这样的疑问,我们先来简单了解一下这五种创建对象的方式。

1 使用 new 关键字

首先我们来介绍的就是我们最常用new关键字。通过这种方式,我们可以调用任意的构造函数(无参的和带参数的)。

Person person = new Person();
Person zhangSan = new Person("张三");
Person lisi = new Person("李四", 28);

2 使用Class类的newInstance方法

这种方式仅能调用无参构造函数,并且还需要抛出异常。

try {
    Person person1 = (Person) Class.forName("com.wx.learn.control.Person").newInstance();
    
    Person person2 = Person.class.newInstance();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

3 使用Constructor类的newInstance方法

这种方式可以根据传入的初始化数据来选择对应的构造函数,但是也是一大波异常抛出。

// method one
try {
    Constructor constructor = Person.class.getConstructor();
    constructor.newInstance();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}// method twotry {
    Constructor constructor = Person.class.getConstructor();
    constructor.newInstance();
} catch (NoSuchMethodException e) {
    e.printStackTrace();
} catch (IllegalAccessException e) {
    e.printStackTrace();
} catch (InstantiationException e) {
    e.printStackTrace();
} catch (InvocationTargetException e) {
    e.printStackTrace();
}

4 使用clone方法

使用clone()方法,需要现在对象中重写clone方法,然后才能让对象调用。并且有一个CloneNotSupportedException异常抛出。而且不会调用构造函数。

Person person = new Person();
try {
    Person personClone = (Person) person.clone();
} catch (CloneNotSupportedException e) {
    e.printStackTrace();
}

5 使用反序列化

使用反序列化无可避免的就是要从字符串变为对象。而且读取数据转换成对象时,会抛出异常。即便你不使用下面的方式,而是使用其他方式来读取,依旧会有异常抛出。而且不会调用构造函数。

try {
    ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
    Person emp5 = (Person) in.readObject();
} catch (IOException e) {
    e.printStackTrace();
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

五种创建对象的方式对比

看到这里,编码经验丰富的小伙伴可能已经猜到原因了。没错,原因只有一个:简单方便!new关键字可以简单直接的就把对象创建出来,而且可以自由选择构造函数。但是其他方式就不一样了。

  • 使用Class类的newInstance方法:
    • 只能使用默认构造函数:意味着你要传几个参数,你就要写几个setter,一个地方还好,很多个地方都用到的话,你是不是要写疯了?难不难受?构造函数用来干啥?摆设吗?
    • 异常抛出!!!
  • 使用Constructor类的newInstance方法:
    • 这个倒是可以选择构造函数了,但是要你传参数,接收还统一是Object,我的天!用这种方式,你参数顺序和构造函数放反了立马就是一个异常,要是类型一致,就更惨了,你查数据排查问题要排查到哭!
    • 异常抛出!!!
  • 使用clone方法:
    • clone方法使用的前提是:你要重写clone方法,另外,你还要有一个已经创建好的对象。所以,理所应当的排除创建对象首选。
    • 异常抛出!!!
  • 使用反序列化:
    • 反序列化的前提是你要有一串序列化好的字符串,你建对象前还要手动去写个符合规则的字符串?
    • 异常抛出!!!

眼尖的小伙伴看到上面四个方法统一的异常抛出这个毛病。使用new,你可以在编码阶段就把异常发现了,但是,你使用其他四种方式,你要等程序运行起来,你才会发现问题。你这么做,是怕你程序异常不够多?还是工作不饱和?

但是,也不是说其他四种创建对象的方式就完全不要用,每种创建对象的方式,都有其存在的价值和使用场景。但是,基本的普通创建对象我们还是使用new关键字来创建,就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值