JAVA基础-反射

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();

本文作者:Hi.PrimaryC

本文链接:https://www.cnblogs.com/cnff/p/17013576.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   primaryC  阅读(18)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.