您现在的位置是:网站首页>博客详情博客详情

Java创建对象的几种方式

边小丰2019年01月30日 Java基础 121人已围观


摘要: Java是一门面向对象的程序设计语言,在日常开发中可能最常见的就是使用new关键字进行对象的创建了。其实创建对象的方式有很多中,在此,准备将实例化对象的方式进行总结,归纳整理。 在此之前,先简单的说明一般会有以下五种方式实例化对象: ①、使用new关键字; ②、使用Class类的newInstance方法; ③、使用Constructor类的newInstance方法; ④、使用Object类的clone方法; ⑤、使用反序列化的方式;

前言

Java是一门面向对象的程序设计语言,在日常开发中可能最常见的就是使用new关键字进行对象的创建了。其实创建对象的方式有很多中,在此,准备将实例化对象的方式进行总结,归纳整理。

在此之前,先简单的说明一般会有以下五种方式实例化对象:

①、使用new关键字;

②、使用Class类的newInstance方法;

③、使用Constructor类的newInstance方法;

④、使用Object类的clone方法;

⑤、使用反序列化的方式;

实例化对象的几种方式

new关键字实例化对象

最常见,也是最简单的实例化对象的方式,通过这种方式,可以调用任意一个构造函数。

如:

    Student student = new Student();
    Student student = new Student("小明");

使用Class类的newInstance方法

使用Class类的newInstance方法,此方法会默认调用对象的无参构造器,所以如果有重写构造器的话需要显式写出无参构造器,否则会报“InstantiationException”异常。

	Student classStudent = (Student) Class.forName("com.dimple.NewObject.Student").newInstance();//需要无参构造器,使用Class的
	classStudent.sayHello();

当然了,也可以这样写:

    Student classStudent = Student.class.newInstance();
	classStudent.sayHello();

使用Student.class代替常常的全限定名。

使用Constructor的newInstance方法

java.lang.reflect.Constructor类中也有一个newInstance方法可以反射创建对象。
查看源码可以看到newInstance的方法如下:


可以看到该方法是有不定参数的,而这个参数最终是调用ConstructorAccessor的newInstance方法的参数,所以Contstructor的newInstance方法是可以调用有参构造器的。

反观Class类的newInstance方法是没有任何参数可以传递的,这也就意味它不能调用有参构造,只能是使用默认的构造器进行实例化。

    Constructor<Student> constructor = Student.class.getConstructor(String.class);
	Student constructorStudent = constructor.newInstance("小明");

Spring、Hibernate、Struts等开源框架,也是采用的这种方式进行实例化对象,并采用复杂的处理对它们进行管理。

使用Clone方法

Clone方法是Object类的方法,而我们知道所有的类的父类都是Object,所以每个类都是可以使用clone方法的。在此之前,此类需要实现Cloneable接口,否则会触发CloneNotSupportedException异常。

		Student clone = (Student) constructorStudent.clone();
		clone.sayHello();

当调用一个对象的clone方法的时候,JVM会创建一个新的对象,然后将该对象的内容全部拷贝到新的对象中。需要注意的是,使用clone方法不会调用构造函数。

使用反序列化

很早之前,在学习流的时候,有一个ObjectInputStream,在书上介绍的时候说到是序列化的时候用到的,当然了,现在整理这些知识的的时候也能够将以前的知识给串通。

把对象转换为字节序列的过程称为对象的序列化。
把字节序列恢复为对象的过程称为对象的反序列化。

java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。

java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。

为了实现序列化,需要让该类实现Serializable接口,否则会触发NotSerializableException异常。

		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("data.o"));
		objectOutputStream.writeObject(clone);
		objectOutputStream.close();

		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("data.o"));
		Student studentSerialization = (Student) objectInputStream.readObject();
		objectInputStream.close();
		studentSerialization.sayHello();

首先是将对象序列化,然后通过反序列化获得一个新的对象,这种方式也是不走构造器的,直接由JVM创建对象。

源码

为了方便说明,也是直接写了几行代码。

package com.dimple.NewObject;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * Created by Dimple on 2018/7/22/20:04
 */
public class Student implements Cloneable {
	private String name;

	//含参构造器
	public Student(String name) {
		this.name = name;
	}

	//无参构造器
	public Student() {
		super();
	}

	//定义的方法
	public void sayHello() {
		System.out.println("Hello " + name);
	}

	public String getName() {
		return name;
	}

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

	//所有异常全部抛出
	public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, CloneNotSupportedException, IOException {
//		1、使用new关键字创建对象
		Student newStudent = new Student("小明");
//		调用对象的方法
		newStudent.sayHello();
//		2、使用Class类的newInstance方法
		Student classStudent = Student.class.newInstance();//需要无参构造器
		classStudent.setName("小明");
		classStudent.sayHello();
//		3、使用Constructor类的newInstance方法
		Constructor<Student> constructor = Student.class.getConstructor(String.class);//说明有参构造器的形参类型
		Student constructorStudent = constructor.newInstance("小明");//使用的是有参构造器
		constructorStudent.sayHello();
//		4、使用Object类的clone方法,需要实现Cloneable接口
		Student clone = (Student) constructorStudent.clone();
		clone.sayHello();
//		5、使用反序列化创建对象,需要实现Serializable接口
//		    先进行序列化
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("data.o"));
		objectOutputStream.writeObject(clone);
		objectOutputStream.close();
//		    再反序列化成为一个新的对象
		ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("data.o"));
		Student studentSerialization = (Student) objectInputStream.readObject();
		objectInputStream.close();
		studentSerialization.sayHello();
	}
}


__EOF__

作  者Dimple
出  处/view/32
版权声明:署名 - 非商业性使用 - 禁止演绎,协议普通文本 | 协议法律文本
声援博主:如果您觉得文章对您有帮助,可以点击下方的鼓掌一下。您的鼓励是博主的最大动力!如有疑问请留言!


文章评论

我的名片

网名:Dimple | 裤兜有怪兽

职业:Java开发工程师

现居:四川省-成都市

Email:bianxiaofeng@sohu.com

每日一句

最近更新

点击排行

猜你喜欢