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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步