JAVA反射总结(3)

上一篇博文,主要回顾了利用反射,可以操作类中的所有方法和属性,本次,我们来使用反射来操作比较特殊的方法:构造方法。第一篇博文已经讲过如何拿构造方法,这里就不多说。本次主要回顾使用构造方法来实例化该反射类对象。

首先依旧是准备好测试类,本次反射测试类是Person.java,该类三个属性以及相应的get和set方法,以及公有和私有的带参与不带参的构造方法。代码如下:

package com.charles.reflectDemo;

public class Person {
	private String name;
	private String desc;
	private int id;
	public Person(String name, String desc, int id)
	{
		this.name = name;
		this.desc = desc;
		this.id = id;
	}
	public Person(String name, String desc) 
	{
		this.name = name;
		this.desc = desc;
	}
	public Person(int id)
	{
		this.id = id;
	}
	public Person()
	{
	}
	private Person (String name)
	{
		this.name=name;
	}
	
	public String person()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}
	public String getDesc()
	{
		return desc;
	}
	public void setDesc(String desc)
	{
		this.desc = desc;
	}
	public int getId()
	{
		return id;
	}
	public void setId(int id)
	{
		this.id = id;
	}
	public String getName() {
		return name;
	}

}

测试类是testDemo3.java,其主要作用如下图:

 

demo1代码如下:

 //先拿person中的所有构造,并显示
	public static void demo1() throws ClassNotFoundException 
	{
		Class<?> PersonClazz=Class.forName("com.charles.reflectDemo.Person");
		Constructor[] constructors=PersonClazz.getDeclaredConstructors();
		for(Constructor constructor: constructors)
		{
			System.out.println(constructor);
		}
	}

执行结果如下图:(这里就不解释了,博文1里面已经提到,这里我们只是用来展示该类的所有构造方法,观察得知,一共有3个公有带参,一个公有无参,1个私有带参,,后面我们用它们来做示例)

demo2代码如下:我们拿一个代表该反射类的公有无参构造方法的对象,通过这个对象来实例化该反射类对象并显示。

//拿公有无参构造,实例化反射类的对象
	public static void demo2() throws ClassNotFoundException
, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
	{
		Class<?> PersonClazz=Class.forName("com.charles.reflectDemo.Person");
		Constructor constructor=PersonClazz.getDeclaredConstructor();
		Person person=(Person)constructor.newInstance();
		person.setName("charles");
		person.setId(123456);
		System.out.println(person.getName()+" "+person.getId());
	}

执行结果如图所示:

 分析:我们通过反射入口Class对象,拿到了代表反射类的一个无参构造的对象:constructor。

Constructor constructor=PersonClazz.getDeclaredConstructor();

之前我们可以通过反射直接实例化该反射类对象,方法是:例如:

Object  reflectDemoObj=reflectDemoClazz.newInstance();

众所周知,在java中我们可以通过new来实例化对象,其本质其实是使用构造函数,比如:Person person=new Person();

所以,通过反射,我们一样可以用构造方法来实例化对象,此例代码如下:

Person person=(Person)constructor.newInstance();

我们通过代表该反射类的构造方法的对象的newInstance();方法来实例化一个对象,返回值为Object类型,我们将其强转为Person类型,再用该Person对象调用该类的set和get方法完成该demo

demo3代码如下:我们拿一个代表该反射类的公有带参构造方法的对象,通过这个对象来实例化该反射类对象并显示。

	//拿公有带参构造,实例化反射类的对象
	public static void demo3() throws ClassNotFoundException
, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
	{
		Class<?> PersonClazz=Class.forName("com.charles.reflectDemo.Person");
		Constructor constructor=PersonClazz.getDeclaredConstructor(int.class);
		Person person=(Person)constructor.newInstance(123456);
		person.setName("charles");
		System.out.println(person.getName()+" "+person.getId());
	}
	

执行结果如图所示:

分析:与demo2类似,都是拿构造方法并实例化对象。但此处的构造方法带参,因此,我们怎么去拿或者是确定带参的构造方法呢?代码如下:    Constructor constructor=PersonClazz.getDeclaredConstructor(int.class);与demo2看起来相似,只是在getDeclaredConstructor(int.class)中多了一个参数,int.class。解释一下,getDeclaredConstructor()这个方法有很多重载,其中参数个数不同但都是Class类型,用来匹配构造函数的参数类型,因为此处我们的Person类有一个只带一个int 型参数的构造方法,所以这里我们只需要写一个int.class  。

注意:不能写成integer.class,这样会报如下异常

Exception in thread "main" java.lang.NoSuchMethodException: com.charles.reflectDemo.Person.<init>(java.lang.Integer)
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.getDeclaredConstructor(Unknown Source)
    at com.charles.reflectDemo.testDemo3.demo3(testDemo3.java:35)
    at com.charles.reflectDemo.testDemo3.main(testDemo3.java:56)

原因:在反射中,基本类型和包装类型是两种不同的类型,例如int和Integer,char和Character,所以需要特别注意一下。

接下来就是利用这个代表构造方法的对象来实例化Person类对象,调用newInstance();方法,该方法也被重载了,此处我们需要填入一个参数,就是你调用构造方法时具体需要传入的值。再用该Person对象调用该类的set和get方法完成该demo;

demo4代码如下:demo2和3都是拿公有构造,此处我们来尝试拿私有带参构造。

//拿私有带参构造,实例化反射类的对象
	public static void demo4() throws ClassNotFoundException
, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException
	{
		Class<?> PersonClazz=Class.forName("com.charles.reflectDemo.Person");
		Constructor constructor=PersonClazz.getDeclaredConstructor(String.class);
        //空白处
		Person person=(Person)constructor.newInstance("charles");
		person.setId(123456);
		System.out.println(person.getName()+" "+person.getId());
	}

执行结果如下所示:异常!

Exception in thread "main" java.lang.IllegalAccessException: Class com.charles.reflectDemo.testDemo3 can not access a member of class com.charles.reflectDemo.Person with modifiers "private"
    at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
    at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(Unknown Source)
    at java.lang.reflect.AccessibleObject.checkAccess(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at com.charles.reflectDemo.testDemo3.demo4(testDemo3.java:47)
    at com.charles.reflectDemo.testDemo3.main(testDemo3.java:57)

分析:观察我们的代码,会发现,似乎基本和demo3一样,但是demo3拿的是公有的构造,我们此处拿的是私有的构造,那么到底哪里不一样呢回想一下之前的博文2,要使用私有属性或者方法,我们必须通过反射来设置让其可以访问。需要设置
constructor.setAccessible(true);,将该代码加在上面代码中标记的空白处,然后执行。观察:正常!

通过上述demo的使用,本次基本可以用反射的构造方法来完成对象的实例化,但是在实际开发或者运用中,一般不要用反射来操作私有属性,方法等,因为这样违背了java的一些特性,会造成代码混乱。好了,demo书写示例完毕!

下一次有空写JAVA反射总结4,利用反射来越过泛型约束,通过配置文件的方式使用泛型,编写泛型工具类等!

over!

原创文章 42 获赞 72 访问量 8229

猜你喜欢

转载自blog.csdn.net/weixin_43249548/article/details/97610913