java中的对象创建一共有几种方式?用学生类来举例说明并创建对象。

准备工作:在做之前我们需要创建一个学生的JavaBean类。

public class Student {
    String name;
    int age;
    int score;

    public Student() {
    }

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return score
     */
    public int getScore() {
        return score;
    }

    /**
     * 设置
     * @param score
     */
    public void setScore(int score) {
        this.score = score;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", score = " + score + "}";
    }
}

方法一:new 关键字

Student stud = new Student("zhangsan",19,96);
System.out.println(stud);

方法二:采用反射创建对象

  1. 获取学生类构造器,指明构造器中的特征,成员变量
  2. 修改构造器权限
  3. 创建对象
 //获取这个类的构造器
Constructor<Student> constructor = Student.class.getDeclaredConstructor(
                String.class,
                int.class,
                int.class
        );
        constructor.setAccessible(true);//调用它的私有方法
        Student s = constructor.newInstance("张三", 18, 100);
        System.out.println(s);

有构造器通过反射创建他的实例对象。好比创建对象后,传递参数 。反射和其他方法相比,还有一个好处是:如果构造方法用private修饰了,那正常其他类肯定是调用不了的这个私有的构造器


方法三:克隆-浅克隆
所谓克隆,就是根据已有的对象创建出来一个新的对象

  1. 前提: 类实现一个Cloneable的接口,并重写里面的clone方法
  2. 注意点:

Ⅰ.根据一个原有的对象去克隆新对象,我们需要把属性也复制过去;对于基本类型会直接赋值,对于引用类型,只会赋值引用地址,并不会产生一个新的引用对象。因此这种克隆我们也称之为浅克隆。
Ⅱ.不会调用原始的构造方法

1.png

 Student s2 = (Student) s.clone();
System.out.println(s2);

方法四:反序列化生成对象 —并不会调用对象的构造方法,会调用父类的构造方法

  1. 前提: 要求类实现Serializable序列化接口
  2. 书写一个对象转换成二进制的方法
 private static byte[] serialize(Student s1) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        //如果序列化主要用到这个类
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(s1);
        byte[] bytes = baos.toByteArray();
        return bytes;

    }

2.png
创建一个ByteArrayOutputStream,关联序列化流ObjectOutputStream,我们把学生对象传递进去,会序列化,ByteArrayOutputStream的作用就是把得到的学生序列化数据写入一个字节数组中,方法作为二进制字节数组作为返回。

  1. 如果再来一次反序列化操作,可以根据二进制形式生成一个新的学生对象,书写一个反序列化操作的方法。
 private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        return ois.readObject();
    }

创建ObjectInputStream 对象关联ByteArrayInputStream,读取字节数组反序列化,最后将反序列化的对象作为方法的返回值

  1. 通过反序列化创建对象
        byte[] bytes = serialize(s);
        //当然这样的方法生成出来的学生对象,和原来的学生对象并不是同一个
        Student s3 = (Student) deserialize(bytes);
        System.out.println(s3);
        System.out.println(s3 == s);//false

方法五:MethodHandle API-执行到构造方法内部

        //找一个类型的构造器
        //参数二MethodType.methodType主要告诉构造器,它的特征,返回值是什么
        //我们可以设置为空参构造,然后有三个成员变量,姓名年龄学分
        //找到构造器方法返回MethodHandle构造器
        //invoke本身就是调用构造方法
        MethodHandle constructor1 = MethodHandles.lookup().findConstructor(Student.class, MethodType.methodType(void.class, String.class, int.class, int.class));
        Student s4 = (Student) constructor1.invoke("李四", 30, 98);
        System.out.println(s4);

源码:Student类

public class Student implements  Cloneable, Serializable {
     String name;
     int age;
     int score;

    public Student() {
    }

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
        System.out.println("我是一个构造方法");
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //调用object继承过来克隆
        return super.clone();
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return score
     */
    public int getScore() {
        return score;
    }

    /**
     * 设置
     * @param score
     */
    public void setScore(int score) {
        this.score = score;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", score = " + score + "}";
    }
}

测试类:

public class CreateObj {
    public static void main(String[] args) throws Throwable {
        Student stud = new Student("zhangsan",19,96);
        System.out.println(stud);
        //获取这个类的构造器
        Constructor<Student> constructor = Student.class.getDeclaredConstructor(
                String.class,
                int.class,
                int.class
        );
        constructor.setAccessible(true);//调用它的私有方法
        Student s = constructor.newInstance("张三", 18, 100);
        System.out.println(s);
        System.out.println("------------------------------------------");
        Student s2 = (Student) s.clone();
        System.out.println(s2);
        System.out.println("-------------------------------------------");
        //把对象转换成二进制形式
        byte[] bytes = serialize(s);
        Student s3 = (Student) deserialize(bytes);
        System.out.println(s3);
        System.out.println(s3 == s);//false
        System.out.println("-------------------------");
        //invoke本身就是调用构造方法
        MethodHandle constructor1 = MethodHandles.lookup().findConstructor(Student.class, MethodType.methodType(void.class, String.class, int.class, int.class));
        Student s4 = (Student) constructor1.invoke("李四", 30, 98);
        System.out.println(s4);
        System.out.println("--------------------------------------");


    }

    private static byte[] serialize(Student s1) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(s1);
        byte[] bytes = baos.toByteArray();
        return bytes;

    }

    private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        return ois.readObject();
    }
}

我书写这篇文章的初衷就是总结学习的进度,遗忘之际可以拿出来翻看,如有不对的地方还望指正,多多海涵。