java --- 反射之了解反射和通过构造 方法实例化对象

个人理解反射可以不通过new这个关键字产生一个指定的类,并可以调用成员变量,普通方法,构造方法等。

首先看一个代码例子

import java.util.Date;
/**
 * 反射取得实例化对象的三种方式
 * @author 76519
 *
 */
public class TestDemo1 {
	public static void main(String[] args) {
		//方式一    需要先实例化类   再反射
		Date date = new Date();
		//此处的泛型   只能是  "?"
		Class<?> dts = date.getClass();
		//System.out.println(dts);
		System.out.println(dts.getName());
		
		//方式二  不需要实例化   但需要引入包----import java.util.Date;
		Class<?> dts2 = Date.class;
		System.out.println(dts2.getName());
		
		//方式三   不需要实例化操作   也无需引入包
		try {
			//根据类名称(全路径名)   反射到类
			Class<?> dts3 = Class.forName("java.util.Date");
			System.out.println(dts3.getName());
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		
		//总结:
			//除了方式一会产生实例化对象之外    其他两种都不会产生实例化对象
	}
}

从例子中可以看出,获取一个反射后的对象有三种方式:

|-实例化对象.getClass();   此方法需要先实例化对象 并导入类的路径  也就是需要先new

|-对象.class;//无需实例化对象  但必须导入类的路径

|-Class.forName("类的全路径"); 无需导入类的路径,因为此时forName中写的就是全路径(包名.类名)

取得一个反射后的类后,可以通过实例化操作,获得此类的操作权。

例子:取得实例化对象

/**
 * 取得实例化对象就意味着取得了一个     指定类    的    操作权
 * @author 76519
 *
 */
public class TestDemo {
	public static void main(String[] args) throws Exception {
		Class<?> cls = Class.forName("java.util.Date");//使用字符串描述使用的类
		//反射出的对象    采取   newInstance()  进行实例化
		Object obj = cls.newInstance();//实例化对象,等价于:new java.util.Date
		System.out.println(obj);
		
		//Object类型   向下  转型
		Date date = (Date) obj;
		System.out.println(date.getTime());
	}
}
Thu Aug 23 10:48:38 CST 2018
1534992518173

   上面是运行结果,newInstance()方法是java.lang.Class的方法,专用于反射类的实例化对象的创建。返回的是一个Object类型,直接打印Object类型的变量是调用了他的toString(),也就是打印的时间。下面的getTime()方法是java.util.Date的方法,Object中不存在,所以需要向下转型。

   此处的代码有个很严重的细节问题,就是"被反射"的类中必须有无参构造(或无参构造不是public修饰的!),下面看个没有无参构造时产生的问题

例子:没有无参引发的血案

class Humen{
	private String userName;
	private int age;
	//无参构造
	//public Humen() {}
	//有参构造
	public Humen(String userName,int age) {
		this.userName = userName;
		this.age=age;
	}
	@Override
	public String toString() {
		return "Humen [userName=" + userName + ", age=" + age + "]";
	}
}
/**
 * 无参的重要性
 * @author 76519
 */
public class TestDemo3 {
	public static void main(String[] args) throws Exception{
		Class<?> humenCls = Humen.class;
		//当没有无参构造时
		//java.lang.NoSuchMethodException: refelect.第二天.Humen.<init>()
		System.out.println(humenCls.newInstance());
	}
}

运行下,出现如下问题:

Exception in thread "main" java.lang.InstantiationException: refelect.Humen
	at java.lang.Class.newInstance(Unknown Source)
	at refelect.TestDemo3.main(TestDemo3.java:29)
Caused by: java.lang.NoSuchMethodException: refelect.Humen.<init>()
	at java.lang.Class.getConstructor0(Unknown Source)
	... 2 more

有人会说到,如果没有无参构造,就不能实例化我获取的反射的类了么,答案是  不是! 有无参构造函数只是说实例化获取到的反射的类更加简单容易,下面我们看下没有无参构造的情况下,如何获取我们反射得到的类的实例化对象。

import java.lang.reflect.Constructor;

class Humen{
	private String userName;
	private int age;
	//无参构造
	//public Humen() {}
	//有参构造
	public Humen(String userName,int age) {
		this.userName = userName;
		this.age=age;
	}
	@Override
	public String toString() {
		return "Humen [userName=" + userName + ", age=" + age + "]";
	}
}
/**
 * 无参的重要性
 * @author 76519
 */
public class TestDemo3 {
	public static void main(String[] args) throws Exception{
		Class<?> humenCls = Humen.class;
		//当没有无参构造时
		//java.lang.NoSuchMethodException: refelect.第二天.Humen.<init>()
		//System.out.println(humenCls.newInstance());
		
		//解决思路
		//通过获取反射对象中的构造方法   实例化对象  ---  此处使用的方法是根据   指定类型获得指定的构造方法
		Constructor<?> cons = humenCls.getConstructor(String.class,int.class);
		//获取构造的对象     并    进行实例化
		System.out.println(cons.newInstance("香蕉不拿拿先生",25));
	}
}

这个方法是获取其他的有参构造方法,通过

 java.lang.Class.getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException

Class对象的getConstructor(Class<?>... parameterTypes)获取指定的构造方法,其中使用到了一个"可变参数"的类型,其实传递的就是一个参数类型的数组,可以是没有,1个或多个参数。

通过获取到指定的构造方法对象后,调用

java.lang.reflect.Constructor.newInstance(Object... initargs) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException

java.lang.reflect.Constructor的newInstance()进行获取反射的实例化对象!

相对于有无参构造函数来说,此方法太麻烦,所以开发中需要写类的无参构造-----我琢磨到这时,才发现无参构造的重要性。

通过以上的方法,我们现在可以利用反射获取到类的对象了,并通过调用其中的构造方法获取实例化对象。

注意:任何该类中的   普通方法   调用,都必须通过先实例化对象,再进行调用普通方法哦。

暂时先说在这吧,后续会继续做出总结

猜你喜欢

转载自blog.csdn.net/qq_38322527/article/details/81976443