Java中对象创建的几种方式
- 本文记录Java创建对象的六种方式,详细内容请查看代码
测试对象
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);
}
}