1,什么是反射?
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。而这也是Java被视为动态(或准动态,为啥要说是准动态,因为一般而言的动态语言定义是程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。)语言的一个关键性质。
2,反射的作用
我们知道反射机制允许程序在运行时取得任何一个已知名称的class的内部信息,包括包括其modifiers(修饰符),fields(属性),methods(方法)等,并可于运行时改变fields内容或调用methods。那么我们便可以更灵活的编写代码,代码可以在运行时装配,无需在组件之间进行源代码链接,降低代码的耦合度;还有动态代理的实现等等;但是需要注意的是反射使用不当会造成很高的资源消耗!
3,反射的具体实现
3.1 获取到 Class 三种方式。
//1、通过对象调用 getClass() 方法来获取,通常应用在:比如你传过来一个 Object
// 类型的对象,而我不知道你具体是什么类,用这种方法
Person p1 = new Person();
Class c1 = p1.getClass();
//2、直接通过 类名.class 的方式得到,该方法最为安全可靠,程序性能更高
// 这说明任何一个类都有一个隐含的静态成员变量 class
Class c2 = Person.class;
//3、通过 Class 对象的 forName() 静态方法来获取,用的最多,
// 但可能抛出 ClassNotFoundException 异常
Class c3 = Class.forName("com.ys.reflex.Person");
需要注意的是:一个类在 JVM 中只会有一个 Class 实例,即我们对上面获取的 c1,c2,c3进行 equals 比较,发现都是true
3.2 获取包名/类名等
Person aClass = Person.class;
aClass.getPackage().getName();
aClass.getSimpleName();
aClass.getName();
aClass.getTypeName();
aClass.getCanonicalName();
3.3 反射构建对象
Person aClass = Person.class;
Person person = aClass.newInstance();
这里必须有无参构造方法
3.4 构造方法
Person aClass = Person.class;
//获取所有 public 构造方法
aClass.getConstructors();
//获取无参构造方法
aClass.getConstructor();
//获取指定参数列表的构造方法
Constructor<? extends Person> constructor = aClass.getConstructor(String.class, int.class);
//使用构造方法构造对象
Person p1 = constructor.newInstance("张三", 10);
3.5 属性
Person aClass = Person.class;
Person p1 = new Person();
//获取指定属性
Field field = aClass.getDeclaredField("name");
//破坏属性 private,protected 等权限设置
field.setAccessible(true);
//获取 p1 对象的属性值
System.out.println( field.get(p1) );
//个 p1 对象的属性赋值
field.set(p1, "李四");
System.out.println(field.get(p1));
Field num = aClass.getDeclaredField("num");
//获取静态属性 num 的值
System.out.println(num.get(null));
num.set(null,10);
//静态属性值获取同样可以通过对象,也可以用 null
System.out.println(num.get(null));
System.out.println(num.get(p1));
num.set(person,20);
//静态属性值设置可以通过 null 来表示,也可以通过对象
System.out.println(num.get(null));
System.out.println(num.get(p1));
-
getDeclaredFields() 和 getFields() 区别在于,getDeclaredFields() 可以无视 private 等权限设置获取属性,getFields() 只能获取 publice 权限的属性。构造方法,方法和属性都是这个规律。
-
如果通过 getDeclaredFields() 获取到的属性,需要通过 field.setAccessible(true) 将权限破坏,否则可能在使用的时候抛出权限异常。
-
静态属性操作可以用 null 表示,通过某个实例也是可以的。
3.6 方法
//获取所有方法
aClass.getMethods();
//获取指定方法,第一个参数是方法名,第二个参数列表类型 Class ...
Method method = aClass.getMethod("run", String.class);
//执行方法,第一个参数对象,第二个参数列表
method.invoke(p1, "北京");
Method staticMethod = aClass.getMethod("staticMethod");
//执行静态方法
staticMethod.invoke(null);
//静态方法也可以通过实例来执行
staticMethod.invoke(p1);
3.7 获取注解
//获取指定类型注解。方法/属性等也有此操作,不再赘述。
Deprecated annotation = aClass.getAnnotation(Deprecated.class);
3.8 判断是否数组
Class aClass = Person.class;
getClass().isArray();
3.9 获取类加载器
aClass.getClassLoader()
3.10 获取父类
Class<?> superclass = aClass.getSuperclass();
标签:aClass,p1,JAVA,反射,获取,基础,Person,class,属性
From: https://www.cnblogs.com/cnff/p/17013576.html