java序列化与反序列化(5)------反序列化时对象的创建方式

原创 2017年10月06日 16:42:33

我在前四篇文章都讲了和序列化相关的东西,在第四篇文章中讲了通过实现Serializable,Cloneable这两个接口来实现深拷贝,但是一直有一个问题值得再讨论一下那就是:反序列化时对象是怎么创建的?

在第四篇文章中我们看到,不管通过实现Cloneable接口还是Serializable来进行深拷贝创建新对象时,都没有调用任何的构造函数进行创建对象,这看起来好像是jvm直接操作内存创建了对象

我们知道java中创建对象的方式有如下三种:

  • 通过new关键字创建对象,这个过程一定是需要调用构造函数的
  • 反射Class.forName(classFullPathName).newInstance()创建对象,一定要调用默认的无参构造函数
  • 通过反射Player.class.getConstructor(int.class,String.class).newInstance()创建对象,一定要调用相应的构造函数
可以运行如下的代码进行测试:
/**
 * 
 * @author yujie.wang
 *
 */
public class CreateObjectTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//createByNew();
		String classFullPathName = "com.yujie.createbean.Player";
		createByReflect1(classFullPathName);
		createByReflect2();
		createByReflect3();
	}
	
	/**
	 * 通过new关键字创建对象 一定显示地调用构造函数
	 */
	public static void createByNew(){
		Player yujie = new Player(20,"yujie.wang");
		yujie.introduceMyself();
	}
	
	/**
	 * 通过反射Class.forName(classFullPathName).newInstance()创建对象
	 * 一定要调用默认的无参构造函数
	 * @param classFullPathName
	 */
	public static void createByReflect1(String classFullPathName){
		if(classFullPathName == null || classFullPathName.isEmpty()){
			System.out.println("classFullPathName == null || classFullPathName.isEmpty()");
		}
		Player yujie = null;	
		try {
			yujie = (Player)Class.forName(classFullPathName).newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		if(yujie != null){
			yujie.introduceMyself();
		}else {
			System.out.println("yujie == null");
		}
	}
	
	/**
	 * 通过反射Class.forName(classFullPathName).newInstance()创建对象
	 * 一定要调用默认的无参构造函数
	 */
	public static void createByReflect2(){
		try {
			Player yujie = Player.class.newInstance();
			yujie.introduceMyself();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	
	/**
	 * 通过反射Player.class.getConstructor(int.class,String.class).newInstance()创建对象
	 * 一定要调用相应的构造函数
	 */
	public static void createByReflect3(){
		try {
			Constructor<Player> c = Player.class.getConstructor(int.class,String.class);
			Player yujie = c.newInstance(20,"yujie.wang");
			yujie.introduceMyself();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
	}
}

我们思考在序列化时写入字节流中确实有类的全路径名,从中我们可以获得Class信息,并可以通过调用构造函数的方式创建对象,但是我们在序列化时并不是将所有的域都序列化了,如果类存在某个构造函数中验证了某些参数的合法性,如果不合法抛出异常的这种逻辑,那么调用构造函数创建对象就会直接抛出异常。这样想来也确实不能够通过调用构造函数创建对象。当然了我们在序列化时并没有要求被序列化的类,一定要提供无参的公共构造函数。这样一分析在不涉及父子继承关系的类进行反序列化时,是不太可能通过调用构造函数进行创建对象的。


版权声明:本文为博主原创文章,未经博主允许不得转载。

GSON使用笔记(2) -- 反序列化时GSON如何创建对象实例

反序列化时GSON如何创建对象实例

xStream xml反序列化时 强转对象相关问题

前几天心血来潮尝试着把公司的ssm框架拷出来,然后把json处理的jar包替换成fastJson,再来个注解自动反序列化,再在request和response上套个base64加密(公司是这么做的,改...
  • boneix
  • boneix
  • 2016年01月12日 16:26
  • 842

java反序列化利用

  • 2017年08月31日 23:54
  • 33.79MB
  • 下载

Java对象反序列化防护

最近一直曝光的开源软件第三方反序列化漏洞: CVE-2015-7501Commons Collections Java反序列化漏洞 Springframework 反序列化RCE漏洞 都是由于Java...

java反序列化利用工具

  • 2016年07月06日 20:05
  • 34.27MB
  • 下载

由Java反序列化对象异常想到的

由Java反序列化对象异常想到的serialVersionUID问题。
  • baosxie
  • baosxie
  • 2017年03月14日 23:06
  • 1507

protostuff序列化集合的问题(反序列化时的java.util.ConcurrentModificationException)

之前写过一篇关于JDK原始支持的Serializable接口序列化与Google的Protostuff序列化两种技术的比较(http://blog.csdn.net/canot/article/det...
  • canot
  • canot
  • 2017年06月10日 16:39
  • 1037
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:java序列化与反序列化(5)------反序列化时对象的创建方式
举报原因:
原因补充:

(最多只允许输入30个字)