Java反射机制
Reflection(反射)是被视为动态语言的关键,反射机制允许程序在执行期借助于 Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
加载完类之后在堆内存的方法区就产生了一个class类型的对象(一个类只有一个class 对象) 这个对象就包含了完整的类结构信息,我们可以
通过这个对象看到类的结构。这个对象就像一面镜子透过这个镜子看到类的结构 所以 我们形象称之为 :反射。
正常方式: 引入需要的“包类”名称 →通过new实例化→取得实例化对象
反射方式 实例化对象→getClass()方法→得到完整的 包类名称
java反射机制提供的功能
1.在运行时判断任意一个对象所属类
2.在运行时构造任意一个类的对象
3.在运行时判断任意一个类所具有的成员变量和方法
4.在运行时获取泛型信息
5.在运行时调用任意一个对象的成员变量和方法
6.在运行时处理注解
7.生成动态代理
一般情况下还是使用直接new 对象的 方式来调用公共结构
关于JAVA.lang.Class 类的理解
1.类的加载过程:程序经过javac.exe命令后 ,会生成一个或多个字节码文件(.class结尾),接着
使用java,exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中国 此过程,称为类的加载
加载到内存中的类 我们就成为运行时类 此运行时类就作为Class的一个实例。
2,换句话说 Class 的实例就对应着一个运行时类
3,加载到内存中的运行时类,会缓存一定的时间,在此时间之内 我们可以通过不同方式来获取此运行时类。
.如何获取Class 的实例
方式一: 调用运行时类的属性:,class
//方式一
Class c = Person.class;
Class<Person> c = Person.class;
方式二: 通过运行时类的对象
Person p1 =new Person();
Class class1 = p1.getClass();
方式三: 调用Class的静态方法 forName(String classPath)
Class class3 = Class.forName("Test.Person");//类的完整路径
哪些类型可以有Class对象
1.class 外部类,成员(成员内部类,静态局部类),局部内部类,匿名内部类
2.interface 接口
3.【 】 数组
4。enum 枚举
5.annotation 注解
6.primitive type : 基本数据类型
7.void
创建运行时类的对象
newInstance() 调用此方法 创建对用的运行时类的对象 内部是调用了运行时类的空参构造器(没有空参构造器会抛异常)
要想此方法正常创建运行时类的对象 要求
1.运行时类必须提供空参构造器
2 空参构造器的访问权限得够 通常设为public
在javabean中要求提供一个public的空参构造器 原因:
1.便于通过反射,创建运行时类的对象
2.便于子类继承此运行时类时 默认调用super()时 保证父类由此构造器
getFields(); 获取当前运行时类及其父类中声明为public访问权限的属性
getDeclaredFields();获取当前运行时类声明的所有属性 跟权限没有关系 不包含父类中的属性
getModifiers() 获取权限修饰符 返回的是int 类型
getType(); //获取数据类型
getName() 获取变量名
getMethods() 获取当前时类及其所有父类中声明为public权限的方法
getDeclaredMethods() 获取当前运行时类声明的所有方法 不包含父类中声明的
getReturnType() 获取返回值类型
getConstructors() 获取当前运行实例中 声明为public 的构造器
getDeclaredConstructors(); 获取当前运行时类中所有的构造器
getSuperclass();获取运行时类的父类
getGenericSuperclass();获取运行时类带泛型的父类
getInterfaces(); 获取运行时类实现的接口 不包括父类的(想要父类可以先获取父类)
getPackage();获取运行时类所在的包
getAnnotation() 获取运行时类声明注解
获取运行时类指定属性
1.(公共权限的)声明为public的
set(); 参数一 : 指明设置哪个对象的属性 参数二 将属性设置为多少
get(); 参数一 获取哪个对象的当前属性值
public static void main(String[] args) throws Exception {
Class clazz = Person.class;
Field field = clazz.getField("age");
//创建运行时类的对象
Person p = (Person) clazz.newInstance();
//设置当前熟悉的值
//参数一 zh
field.set(p,1001);
Object object = field.get(p);
System.out.println(object);
}
方式二 :不止公共的可以访问
setAccessible(true); 权限
1.创建运行时类的对象
2.getDeclaredField(String fieldName) 获取运行时类中指定变量名的属性
3.保证当前属性是可访问的
4,获取设置指定对象的此属性值
Class clazz = Person.class;
Person o = (Person) clazz.newInstance();
//获取指定变量名的属性
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
f.set(o, 500);
System.out.println(f.get(o));
获取运行时类指定方法
getDeclaredMethod();
参数一 指明获取方法名
参数二 可能有同名方法 参数二指明获取的方法的形参列表
invoke();
invoke()的返回值即为对应类中调用的方法的返回值
参数一 方法调用者
参数二 方法的实参 (给方法赋值)
Class clazz= Person.class;
Person p = (Person) clazz.newInstance();
Method show = clazz.getDeclaredMethod("show", String.class);
show.setAccessible(true);
show.invoke(p, "chn");
如果调用的运行时类中的方法没有返回值 则此invoke()返回null
若上面方法为静态的则 invoke()的参数一写啥都可以
调用运行时类指定构造器(不常用)
1.获取指定构造器 getDeclaredConstructor() 参数 指明构造器参数列表 String.class …
2.保证该构造器是可访问的
3.调用此构造器创建运行时类的对象
Class clazz =Person.class;
Constructor c = clazz.getDeclaredConstructor(String.class);
c.setAccessible(true);
Person p = (Person) c.newInstance("小尤");
System.out.println(p);