Java中创建对象的几种方法

概况

据我所知,Java创建对象有以下几种方法:

  1. 使用new关键字
  2. 使用Class类的newInstance方法
  3. 使用Constructor类的newInstance方法
  4. 使用Clone的方法
  5. 使用反序列化

下面我们来一一练习。

获取类的位置和名称

package 获取类的位置和名称;

import pojo.Person;

public class GetClassName {
	public static void main(String[] args) {
        Class<?> demo2=null;
        Class<?> demo3=null;
        //方式1
        demo2=new Person().getClass();
        
        //方式2
        demo3=Person.class;
        
        System.out.println("类名称   "+demo2.getName());
        System.out.println("类名称   "+demo3.getName());
    }
}

Class类

package 无参数反射;

import pojo.Person;

public class TestClassNewInstance {
	public static void main(String[] args) {
		//想反射创建对象,首先我们需要知道类的位置和名称
		//这句话获取类的包名和类名
		String p=Person.class.getName();
		System.out.println("对象的包名+类名:"+p);
		
		 Class<?> demo=null;
	       try{
	           demo=Class.forName(p);
	          /*
	           * 笔记:
	           * Class.forName(xxx.xx.xx) 返回的是一个类 
	           * 作用是要求JVM查找并加载指定的类,也就是说JVM会执行该类的静态代码段
	           * 
	           * 从JVM的角度看,我们使用关键字new创建一个类的时候,这个类可以没有被加载。
	           * 但是使用newInstance()方法的时候,就必须保证:
	           * 1、这个类已经加载;
	           * 2、这个类已经连接了。
	           * 而完成上面两个步骤的正是Class的静态方法forName()所完成的,
	           * 这个静态方法调用了启动类加载器,即加载java API的那个加载器。 
	           * 
	           * 
	           * newInstance: 弱类型。低效率。
	           * new: 强类型。相对高效。能调用任何public构造。
	           */
	           
	       }catch (Exception e) {
	           e.printStackTrace();
	       }
	       Person per=null;
	       try {
	    	   //下面的“(Person)”可以换成demo实现的接口
	           per=(Person)demo.newInstance();
	       } catch (InstantiationException e) {
	           e.printStackTrace();
	       } catch (IllegalAccessException e) {
	           e.printStackTrace();
	       }
	       per.setName("周星驰");
	       per.setAge(20);
	       System.out.println(per);
	}

}
package 有参数反射;

import java.lang.reflect.Constructor;

import pojo.User;

public class ClassNewInstance {
	public static void main(String[] args) {
		// 这句话获取类的包名和类名
		String p = User.class.getName();
		Class<?> demo = null;
		try {
			demo = Class.forName(p);
		} catch (Exception e) {
			e.printStackTrace();
		}
		User per0 = null;
		User per1 = null;
		User per2 = null;
		User per3 = null;
		User per4 = null;
		// 取得全部的构造函数
		Constructor<?> cons[] = demo.getConstructors();
		System.out.println(cons.length);

		try {
			// 默认的构造函数的下标最大,User一个有五个构造函数,所以默认构造函数的下标为4
			per0 = (User) cons[4].newInstance();
			// 构造函数1
			per1 = (User) cons[0].newInstance("Rollen");
			// 构造函数2
			per2 = (User) cons[1].newInstance(20);
			// 构造函数3
			per3 = (User) cons[2].newInstance("Rollen", "周星星");
			// 构造函数4
			per4 = (User) cons[3].newInstance("Rollen", 20, "周星星");

		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(per0);
		System.out.println(per1);
		System.out.println(per2);
		System.out.println(per3);
		System.out.println(per4);
	}

}

Constructor类

package 有参数反射;

import java.lang.reflect.Constructor;

import pojo.User;

public class ConstructorNewInstance {
	/*
	 * newInstance() 的参数版本与无参数版本详解
	 * 
	 * 通过反射创建新的类示例,有两种方式: Class.newInstance() Constructor.newInstance()
	 * 
	 * 以下对两种调用方式给以比较说明: Class.newInstance() 只能够调用无参的构造函数,即默认的构造函数;
	 * Constructor.newInstance() 可以根据传入的参数,调用任意构造构造函数。
	 * 
	 * Class.newInstance() 抛出所有由被调用构造函数抛出的异常。
	 * 
	 * Class.newInstance() 要求被调用的构造函数是可见的,也即必须是public类型的;
	 * Constructor.newInstance() 在特定的情况下,可以调用私有的构造函数。
	 */

	public static void main(String[] args) {
		String className = User.class.getName();
		try {
			/* 可以使用相对路径,同一个包中可以不用带包路径 */
			Class<?> c = Class.forName(className);
			/* 以下调用无参的、私有构造函数 */
			Constructor<?> con1 = c.getDeclaredConstructor();
			/*
			 * 笔记: 在类的外面获取此类的私有成员变量的value时 将此对象的 accessible 标志设置为指示的布尔值。 值为 true
			 * 则指示反射的对象在使用时应该取消 Java 语言访问检查。 值为 false 则指示反射的对象应该实施 Java 语言访问检查。
			 * 实际上setAccessible是启用和禁用访问安全检查的开关,并不是为true就能访问为false就不能访问
			 * 
			 * 
			 * 如果有private修饰,默认accessible为false,则会报错
			 * java.lang.IllegalAccessException: Class
			 * 有参数反射.ConstructorNewInstance can not access a member of class
			 * pojo.User with modifiers "private"at
			 * sun.reflect.Reflection.ensureMemberAccess(Unknown Source)at
			 * java.lang.reflect.Constructor.newInstance(Unknown Source)at
			 * 有参数反射.ConstructorNewInstance.main(ConstructorNewInstance.java:42)
			 */
			con1.setAccessible(true);
			User user01 = (User) con1.newInstance();
			/* 以下调用带参的、私有构造函数 */
			Constructor<?> con2 = c.getDeclaredConstructor(new Class[] {
					String.class, String.class });
			con2.setAccessible(true);
			User user02 = (User) con2
					.newInstance(new Object[] { "jevon", "李叔叔" });

			System.out.println("调用无参的:" + user01);
			System.out.println("调用带参的:" + user02);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

Clone方法

Person p = new Person(23, "zhang");  
Person p1 = p;  
  
System.out.println(p);  
System.out.println(p1); 

深入研究参考博客:http://blog.csdn.net/u011679955/article/details/52736379

反序列化

参考博客:

http://www.cnblogs.com/fuck1/p/5462052.html

http://blog.csdn.net/wangloveall/article/details/7992448/

 

转载于:https://my.oschina.net/Jevon95/blog/891440

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值