Java中对象创建的几种方式

Java中对象创建的几种方式

  • 本文记录Java创建对象的种方式,详细内容请查看代码
测试对象
  • 粘贴复制即可,配合TestPeople食用
import java.io.Serializable;

/**
 * @author unknown
 * @since 2023/09/01 16:09
 */
public class People implements Cloneable , Serializable {

    private int age;

    private String name;


    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

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

    public People() {
        System.out.println("调用了无参构造方法");
    }

    protected People(int age, String name) {
        this.name = name;
        this.age = age;
        System.out.println("调用了有参构造方法");
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", age='" + age + '\'' +
                '}';
    }


}

测试示例
import org.junit.jupiter.api.Test;
import sun.misc.Unsafe;

import java.io.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

/**
 * <P>对象的几种创建方式测试</P>
 * @author unknown
 * @since 2023/09/01 16:13
 */

public class TestPeople {


    /**
     * <P>new关键字创建</P>
     */
    @Test
    public void TestNew (){

        People people = new People();
        System.out.println(people);
    }

    /**
     * <P>克隆创建</P>
     * 如果使用使用此方式创建,对象必须实现Cloneable并且重写Object的clone方法
     * @see com.example.blog.test.base.People
     *
     */
    @Test
    public void TestClone () throws CloneNotSupportedException {

        // 在行克隆后,引用类型(String,Object)的克隆是引用地址值,基本类型(int,long等等)的则是复制值,并不会调用对象的构造方法. 此方法称为-浅克隆
        People clone = (People) new People(1,"张三").clone();
        // 当运行此方法后会发现控制台输出了-> 调用了有参构造方法,这个输出是关键字new使用的有参构造方法,并不是在克隆时调用People的构造方法创建clone对象
        System.out.println(clone);
    }

    /**
     * <P>序列化创建</P>
     * 如果使用使用此方式创建,对象必须实现Serializable接口
     * @see com.example.blog.test.base.People
     */
    @Test
    public void TestSerializable () throws IOException, ClassNotFoundException {

        People people = new People(1, "张三");
        System.out.println(people);

        // 序列化
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectInputStream = new ObjectOutputStream(byteArrayOutputStream);
        objectInputStream.writeObject(people);
        byte[] byteArray = byteArrayOutputStream.toByteArray();

        // 反序列化,在反序列化的时候,并不会调用People的构造方法
        ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(byteArray));
        People deserializable = (People)inputStream.readObject();
        System.out.println("反序列化"+deserializable);
    }

    /**
     * <P>反射创建</P>
     * 利用有参构造方法创建,在给定形参类型和参数值的时候,一定要按照People有构造方法的顺序给定
     */
    @Test
    public void testReflex () throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

        // 获取有参的构造器
        Constructor<People> declaredConstructor = People.class.getDeclaredConstructor(int.class, String.class);
        // 假设对象的有参构造方法是private修饰的,那就无法利用构造器创建对象,以下是解决方法
//         declaredConstructor.setAccessible(true);
        // 利用有参构造器创建对象
        People people = declaredConstructor.newInstance(1, "张三");
        System.out.println(people);

    }

    /**
     * <P>MethodHandle API创建</P>
     * 利用有参构造方法创建,在给定形参类型和参数值的时候,一定要按照People有构造方法的顺序给定
     */
    @Test
    public void TestMethodHandles () throws Throwable {

        // 利用methodHandle给定类型创建构造器
        MethodHandle constructor = MethodHandles.lookup().findConstructor(People.class, MethodType.methodType(void.class, int.class, String.class));
        // 利用有参构造器创建对象
        People people = (People)constructor.invoke(1,"1" );
        System.out.println(people);
    }

    /**
     * <P>Unsafe创建</P>
     * Unsafe可以直接访问系统内存资源、自主管理内存资源等,慎用!
     * @see sun.misc.Unsafe
     */
    @Test
    public void TestUnsafe () throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {

        //创建Unsafe对象
        Class<Unsafe> unsafeClass = Unsafe.class;

        // 第一种方式:通过构造器获取Unsafe实例
        Constructor<Unsafe> declaredConstructor = unsafeClass.getDeclaredConstructor();
        // 假设对象的有参构造方法是private修饰的,那就无法利用构造器创建对象,以下是解决方法
        declaredConstructor.setAccessible(true);
        Unsafe unsafe1 = declaredConstructor.newInstance();
        People people = (People)unsafe1.allocateInstance(People.class);
        people.setName("张三");
        System.out.println(people);

        // 第二种方法:通过字段获取Unsafe实例
        Field theUnsafe = unsafeClass.getDeclaredField("theUnsafe");
        // 假设对象的有参构造方法是private修饰的,那就无法利用构造器创建对象,以下是解决方法
        theUnsafe.setAccessible(true);
        Unsafe unsafe2 = (Unsafe)theUnsafe.get(null);
        People people1 = (People)unsafe2.allocateInstance(People.class);
        people.setName("李四");
        System.out.println(people1);

    }

}
posted @ 2023-09-01 18:53  unknown-n2  阅读(26)  评论(0编辑  收藏  举报