反射机制概念:
通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
反射的应用场景
Class类
Class是一个特殊的类,不是用来声明类的关键字,Class类的首字母是大写的。,它同样继承自Object类,可以用Class类的对象来描述一个类中的成员
Class对象的获取
//方式一:(getClass()方法是object类的方法)
Class c1 = new Person().getClass();
//方式二:
Class c1 = Person.class;
//方式三:使用Class类的静态方法(最常用)
Class c1 = Class.forName(“类的全限定名”)
ps:
1. 方式三会抛出异常,要捕获处理。
2. 参数要填写类的全限定名,从src下一级目录开始
3. 如果要获取一个内部类的Class对象,注意在最后一层要改成 "$内部类名",而不再是靠点(.)连接
反射对象的实例化
//Class其实是有泛型的,此处没有写,默认是object类型,也正好符合了反射的场景需求,反射要的就是动态的获得对象
Class c = Class.forName(“类的全限定名”);
//动态实例化一个c所描述的对象,默认调用的是这个类中的无参构造方法,如果没有无参或者private权限的无参构造,则会报错
Object obj = c.newInstance();
//通过制定构造函数,获取实例化对象
//getConstructor()要求获取的构造参数必须是public权限,而且参数类型要对
//getConstructor()也可以获取到无参的构造函数
Constructor c1 = c.getConstructor(String.class,int.class);
Object obj1 = c1.newInstance("小明",10); //要赋实值
//可以获得任何权限的构造方法,破单例
/**
如果获得的构造参数为私有的,获得是可以获得,但是无法new一个对象,仍然无法获得一个对象
此时,使用setAccessible(true)可以设置在使用前是否进行权限的检查,如果设置为true,则不进行检查,直接使用,反之要进行权限的检查
备注:同样可以获得无参构造
*/
Constructor c2 = c.getDeclaredConstructor(String.class,int.class);
c2.setAccessible(true);
Object obj2 = c2.newInstance("LAOWANG",20);
获取构造方法
//获取一个类中所有的构造方法,只获取public权限的
Constructor[] getConstructors();
//获取一个类中所有的构造方法,获取所有权限的,有没有参数都可以
Constructor[] getDeclaredConstructors();
访问动态类的属性
//获取属性,c是Class对象,而不是实例化的一个对象,获取的是一个public权限的属性
Field fieldName = c.getField("name");
//获取属性的类型
fieldName.getType()
//获取属性的名字
fieldName.getName()
//获取一个对象的属性值,获取哪个对象的该属性值需要指出
fieldName.get(对象)
//获取非public权限的属性
Field fieldName1=c.getDeclaredField("age")
//不检验,可以使用非public权限的
fieldName1.setAccessible(true)
//设置对象的属性
//对象是指该属性属于哪个对象,值是给她赋值
fieldName.set(对象,值)
访问动态类的方法
//获取方法
Method m = c.getDeclaredMethod();
//获取方法名
m.getName()
//获取参数类型
m.getParameterTypes()
//获取返回值类型
m.getReturnType()
//获取一个非public权限的方法
Method m = c.getDeclaredMethod(方法名,参数类型.class);
//调用方法
m.invoke(对象名,参数)
小知识点:
m.getMethods()获取的方法都是public权限,包括继承而来的。
但是m.getDeclaredMethod()获取了所有权限的方法,但是不包括继承而来的方法