专栏首页KIWI的碎碎念创建 Java 对象有几种写法?

创建 Java 对象有几种写法?

创建 Java 对象有几种写法?

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

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

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

测试对象代码 Person.java

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();
    }
}

创建对象代码

    /**
     * 通过 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 对象的方法也有好几种,这里直接通过类来获得。代码如下:

创建对象代码

    /**
     * 通过类反射
     */
    @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 没有无参构造函数时,框架就会报错,他是不会帮你用第三种的。代码如下:

创建对象代码

    /**
     * 通过构建函数反射创建
     * @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 方法就可以创建一个一毛一样的对象。需要注意的是这是是浅克隆,啥是浅克隆?浅克隆是指复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。也就是说修改克隆后的对象中的引用变量,也会导致原对象也产生变化。深克隆反之。代码如下:

创建对象代码

    /**
     * 通过克隆
     */
    @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

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);
    }
}

创建对象代码

    /**
     * 通过反序列化
     * @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 对象创建方法了。由此可以看出单例模式是无法保证系统中只有一个对象的。

本文分享自微信公众号 - KIWI的碎碎念(kiwiflydream),作者:kiwi

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Rocketmq】通过 docker 快速搭建 rocketmq 环境

    {RmHome} 要替换成你的宿主机想保存 MQ 的日志与数据的地方,通过 docker 的 -v 参数使用 volume 功能,把你本地的目录映射到容器内的...

    KIWI
  • 【spock】单测竟然可以如此丝滑

    在之前的关于swagger文章里提到过,程序员最讨厌的两件事,一件是别人不写文档,另一件就是自己写文档。这里如果把文档换成单元测试也同样成立。每个开发人员都明白...

    KIWI
  • 【随笔】开源之殇

    这两天有个新闻[1]比较火,一个叫丹尼斯·普什卡列夫的俄罗斯程序员,因为骑车撞人被判 18 个月。骑车撞人可能不是什么大新闻,造成严重后果的,被判刑也无可厚非。

    KIWI
  • Java类库之比较器(重点)

    如果现在要想为一组对象进行排序,那么必须有一个可以区分出对象大小的关系操作,而这个操作在Java之中就是利用比较器完成的。常用比较器:Comparable(核心...

    葆宁
  • java之Lombok

    针对上面的介绍,我们简要说下它,首先它是一个java库,它通过注解的方式使你不用再为成员属性生成get/set等其它方法,就是说它简化了你程序的代码了,使程序的...

    后端Coder
  • 蚂蚁区块链第14课 如何在TEE硬件隐私加密链上搭建一个DAPP应用(以姓名年龄为例)

    本文介绍通过调用蚂蚁BAAS的TEE硬件隐私链的JS SDK,完成智能合约读取,编译和加密部署功能。然后通过基于EXPRESS框架搭建的前端页面完成该姓名/年龄...

    辉哥
  • 第1次Spring源码学习之@Bean、@Configuration、xml、分析

    TrueDei
  • ES6语法中类(class)的实现原理

    JavaScript语言不同于其他的类C语言,没有提供类的概念,但是可以提供类似的语法糖来实现JS面向对象的编程范式,本质上不是严格意义上的类

    伯爵
  • Docker下,极速体验mongodb

    MongoDB是基于分布式文件存储的数据库,旨在为WEB应用提供可扩展的高性能数据存储解决方案。 下载镜像 在Docker环境下很容易搭建一个mongodb单机...

    程序员欣宸
  • 格式化输出

    比如要求用户输入用户名和年龄,然后打印如下格式:My name is xxx,my age is xxx.

    py3study

扫码关注云+社区

领取腾讯云代金券