前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >创建 Java 对象有几种写法?

创建 Java 对象有几种写法?

作者头像
KIWI
发布2020-04-08 11:27:03
1.3K0
发布2020-04-08 11:27:03
举报
文章被收录于专栏:KIWI的碎碎念

创建 Java 对象有几种写法?

创建 Java 对象,跟"回"字一样也有好几种写法。虽然简单,但是也涉及到了几个 Java 关键的基础知识,比如反射、克隆、序列化与反序列化,所以面试也经常会遇到,然后不断扩展的问。

第一种:通过 new 关键字创建

这一种没啥好说的,从学 Java 第一天就不停的跟两样东西打交道,一个的是 new 关键字,一个是NullPointerException ?。代码如下

测试对象代码 Person.java

代码语言:javascript
复制
package cn.coder4j.blog.demo.code.crete.object.method;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

/**
 * 人员类
 */
public class Person implements Cloneable {
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 用户名
     */
    private String name;

    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Person() {
    }

    /**
     * Getter method for property <tt>age</tt>.
     *
     * @return property value of age
     */
    public Integer getAge() {
        return age;
    }

    /**
     * Setter method for property <tt>age</tt>.
     *
     * @param age value to be assigned to property age
     */
    public void setAge(Integer age) {
        this.age = age;
    }

    /**
     * Getter method for property <tt>name</tt>.
     *
     * @return property value of name
     */
    public String getName() {
        return name;
    }

    /**
     * Setter method for property <tt>name</tt>.
     *
     * @param name value to be assigned to property name
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return ReflectionToStringBuilder.reflectionToString(this,
                ToStringStyle.SHORT_PREFIX_STYLE);
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

创建对象代码

代码语言:javascript
复制
    /**
     * 通过 new 关键字去创建对象
     */
    @Test
    public void testNew() {
        Person person = new Person();
        person.setAge(18);
        person.setName("kiwi");

        System.out.println(person);
    }

第二种:通过 class 的 newInstance_() 方法_

这里就涉及到了 Java 基础里面的反射知识了,大多数框架也是通过这种方式创建的对象,比如说 spring。通过反射拿到 class 对象,再直接调用 newInstance() 方法就可以直接创建出一个对象。获得 class 对象的方法也有好几种,这里直接通过类来获得。代码如下:

创建对象代码

代码语言:javascript
复制
    /**
     * 通过类反射
     */
    @Test
    public void testClassReflect() throws IllegalAccessException, InstantiationException {
        Person person = Person.class.newInstance();
        person.setAge(18);
        person.setName("kiwi");

        System.out.println(person);
    }

第三种:通过 constructor 的 newInstance() 方法

与第二种方法一样,同样是通过反射。也是拿到 class 对象,不过这里,拿到对象后,又多了一步去拿构造函数。可能有人觉得疑问了,与第二种达到的结果是一样的,但是还要多写一些代码,为什么还要用他。其实对于有无参构造函数的类来说,两种方法都一样,哪个都可以使用。但是是对于只有有参构造函数的类来说,只能使用第三种。因为第二种无法指定构建函数。所以因为大多数框架使用的都是第二种包括 spring,所以当你的 bean 没有无参构造函数时,框架就会报错,他是不会帮你用第三种的。代码如下:

创建对象代码

代码语言:javascript
复制
    /**
     * 通过构建函数反射创建
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    @Test
    public void testConstructReflect() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<Person> constructor = Person.class.getConstructor();
        Person person = constructor.newInstance();
        person.setAge(18);
        person.setName("kiwi");

        System.out.println(person);
    }

    /**
     * 通过有参构造函数反射创建
     * @throws NoSuchMethodException
     * @throws IllegalAccessException
     * @throws InvocationTargetException
     * @throws InstantiationException
     */
    @Test
    public void testConstructWithParamReflect() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Constructor<Person> constructor = Person.class.getConstructor(Integer.class, String.class);
        Person person = constructor.newInstance(18, "kiwi");

        System.out.println(person);
    }

第四种:通过 clone

可以看到 Person.java 实现了接口 Cloneable 并覆盖了 clone 方法(其实只是调用了父类方法),然后调用对象的 clone 方法就可以创建一个一毛一样的对象。需要注意的是这是是浅克隆,啥是浅克隆?浅克隆是指复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说修改克隆后的对象中的引用变量,也会导致原对象也产生变化。深克隆反之。代码如下:

创建对象代码

代码语言:javascript
复制
    /**
     * 通过克隆
     */
    @Test
    public void testClone() throws CloneNotSupportedException {
        Person person = new Person();
        person.setAge(18);
        person.setName("kiwi");

        Person personClone = (Person)person.clone();
        System.out.println(personClone);
    }

第五种:通过反序列化

序列化与反序列化有很多种,包括 json,xml 其实都是。这里使用的是 java 原生的 Serializable 实现的序列化。很多 rpc 框架,比如 dubbo 使用的就是这种方式,这里需要类实现 jdk 的 Serializable 接口,并且给他一个 serialVersionUID 属性。代码如下:

测试对象代码 PersonDto.java

代码语言:javascript
复制
package cn.coder4j.blog.demo.code.crete.object.method;

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;

import java.io.Serializable;

/**
 * 人员类
 */
public class PersonDto implements Serializable {
    private static final long serialVersionUID = 3911118195380172132L;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 用户名
     */
    private String name;

    public PersonDto(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public PersonDto() {
    }

    /**
     * Getter method for property <tt>age</tt>.
     *
     * @return property value of age
     */
    public Integer getAge() {
        return age;
    }

    /**
     * Setter method for property <tt>age</tt>.
     *
     * @param age value to be assigned to property age
     */
    public void setAge(Integer age) {
        this.age = age;
    }

    /**
     * Getter method for property <tt>name</tt>.
     *
     * @return property value of name
     */
    public String getName() {
        return name;
    }

    /**
     * Setter method for property <tt>name</tt>.
     *
     * @param name value to be assigned to property name
     */
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return ReflectionToStringBuilder.reflectionToString(this,
                ToStringStyle.SHORT_PREFIX_STYLE);
    }
}

创建对象代码

代码语言:javascript
复制
    /**
     * 通过反序列化
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Test
    public void testSerializable() throws IOException, ClassNotFoundException {
        PersonDto person = new PersonDto();
        person.setAge(18);
        person.setName("kiwi");

        // 把对象序列化
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person"));
        oos.writeObject(person);
        oos.close();

        // 反序列化
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person"));
        PersonDto personSeri = (PersonDto) ois.readObject();
        System.out.println(personSeri);
    }

这里就说完了,比较常用的几种 Java 对象创建方法了。由此可以看出单例模式是无法保证系统中只有一个对象的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 KIWI的碎碎念 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 创建 Java 对象有几种写法?
    • 第一种:通过 new 关键字创建
      • 测试对象代码 Person.java
        • 创建对象代码
          • 第二种:通过 class 的 newInstance_() 方法_
            • 创建对象代码
              • 第三种:通过 constructor 的 newInstance() 方法
                • 创建对象代码
                  • 第四种:通过 clone
                    • 创建对象代码
                      • 第五种:通过反序列化
                        • 测试对象代码 PersonDto.java
                          • 创建对象代码
                          相关产品与服务
                          文件存储
                          文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档