博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java反射
阅读量:4324 次
发布时间:2019-06-06

本文共 5371 字,大约阅读时间需要 17 分钟。

Java 反射是可以让我们在运行时获取类的函数、属性、父类、接口等 Class 内部信息的机制。通过反射还可以让我们在运行期实例化对象,调用方法,通过调用 get/set 方法获取变量的值,即使方法或属性是私有的的也可以通过反射的形式调用.

当我们编写完一个 Java 项目之后,所有的 Java 文件都会被编译成一个.class 文件,这些 Class 对象承载了这个类型的父类、接口、构造函数、方法、属性等原始信息,这些 class 文件在程序运行时会被 ClassLoader 加载到虚拟机中。当一个类被加载以后,Java 虚拟机就

会在内存中自动产生一个 Class 对象。我们通过 new 的形式创建对象实际上就是通过这些 Class 来创建,只是这个过程对于我们是不透明的而已。

1.如果你在编译期知道一个类的名字的话,那么你可以使用如下的方式获取一个类的 Class 对象。

Class
myObjectClass = MyObject.class;

2.如果你已经得到了某个对象,但是你想获取这个对象的 Class 对象,那么你可以通过下面的方法得到:

Student me = new Student("mr.simple");Class
clazz = me.getClass();

3.如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class 对象:

Class
myObjectClass = Class.forName("com.simple.User"); 接口说明
// 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student". ( 常用方式 )public static Class
forName (String className)// 加载指定的 Class 对象,参数 1 为要加载的类的完整路径,例如"com.simple.Student";// 参数 2 为是否要初始化该 Class 对象,参数 3 为指定加载该类的 ClassLoader.public static Class
forName (String className, boolean shouldInitialize, ClassLoader classLoader)

通过 Class 对象构造目标类型的对象:

private static void classForName() {        try {            // 获取 Class 对象            Class
clz = Class.forName("org.java.advance.reflect.Student"); // 通过 Class 对象获取 Constructor,Student 的构造函数有一个字符串参数 // 因此这里需要传递参数的类型 ( Student 类见后面的代码 ) Constructor
constructor = clz.getConstructor(String.class); // 通过 Constructor 来创建 Student 对象 Object obj = constructor.newInstance("mr.simple"); System.out.println(" obj : " + obj.toString()); } catch (Exception e) { e.printStackTrace(); } }
接口说明
// 获取一个公有的构造函数,参数为可变参数,如果构造函数有参数,那么需要将参数的类型传递给 getConstructor 方法 public Constructor
getConstructor (Class...
parameterTypes) // 获取目标类所有的公有构造函数 public Constructor[]
getConstructors ()

     私有方法调用必须设置accessible为true,不进行java语言访问检查

Constructor
constructor = clz.getConstructor(String.class); // 设置 Constructor 的 Accessible constructor.setAccessible(true); // 设置 Methohd 的 Accessible Method learnMethod = Student.class.getMethod("learn", String.class); learnMethod.setAccessible(true); 获取方法: 要获取当前类中定义的所有方法可以通过 Class 中的 getDeclaredMethods 函数,它会获取到当前类中的 public、default、protected、private 的所有方法。 而 getDeclaredMethod(String name, Class...
parameterTypes)则是获取某个指定的方法 要获取当前类以及父类中的所有 public 方法可以通过 Class 中的 getMethods 函数,而 getMethod 则是获取某个指定的方法

   接口说明

// 获取 Class 对象中指定函数名和参数的函数,参数一为函数名,参数 2 为参数类型列表public Method getDeclaredMethod (String name, Class...
parameterTypes)// 获取该 Class 对象中的所有函数( 不包含从父类继承的函数 )public Method[] getDeclaredMethods ()// 获取指定的 Class 对象中的**公有**函数,参数一为函数名,参数 2 为参数类型列表public Method getMethod (String name, Class...
parameterTypes)// 获取该 Class 对象中的所有**公有**函数 ( 包含从父类和接口类集成下来的函数 )public Method[] getMethods ()
这里需要注意的是 getDeclaredMethod 和 getDeclaredMethods 包含 private、protected、default、public 的函数,并且通过这两个函数获取到的只是在自身中定义的函数,从父类中集成的函数不能够获取到。 而 getMethod 和 getMethods 只包含 public 函数,父类中的公有函数也能够获取到。  获取属性: 要获取当前类中定义的所有属性可以通过 Class 中的 getDeclaredFields 函数,它会获取到当前类中的 public、default、protected、private 的所有属性。 而 getDeclaredField 则是获取某个指定的属性 要获取当前类以及父类中的所有 public 属性可以通过 Class 中的 getFields 函数,而 getField 则是获取某个指定的属性。

    接口说明

// 获取 Class 对象中指定属性名的属性,参数一为属性名public Method getDeclaredField (String name)// 获取该 Class 对象中的所有属性( 不包含从父类继承的属性 )public Method[] getDeclaredFields ()// 获取指定的 Class 对象中的**公有**属性,参数一为属性名public Method getField (String name)// 获取该 Class 对象中的所有**公有**属性 ( 包含从父类和接口类集成下来的公有属性 )public Method[] getFields ()
这里需要注意的是 getDeclaredField 和 getDeclaredFields 包含 private、protected、default、public 的属性,并且通过这两个函数获取到的只是在自身中定义的属性,从父类中集成的属性不能够获取到。 而 getField 和 getFields 只包含 public 属性,父类中的公有属性也能够获取到。 获取 Class 对象的父类:
Student student = new Student("mr.simple");    Class
superClass = student.getClass().getSuperclass(); while (superClass != null) { System.out.println("Student's super class is : " + superClass.getName()); // 再获取父类的上一层父类,直到最后的 Object 类,Object 的父类为 null superClass = superClass.getSuperclass(); }

   获取 Class 对象中实现的接口:

private static void showInterfaces() {        Student student = new Student("mr.simple");        Class
[] interfaceses = student.getClass().getInterfaces(); for (Class
class1 : interfaceses) { System.out.println("Student's interface is : " + class1.getName()); } }

 

  获取注解:

通过反射 api 我们也能够获取一个 Class 对象获取类型、属性、函数等相关的对象,通过这些对象的 getAnnotation 接口获取到对应的注解信息。 如
@Test(tag = "Student class Test Annoatation")public class Student extends Person implements Examination {    // 年级    @Test(tag = "mGrade Test Annotation ")    int mGrade;    // ......}

然后通过相关的注解函数得到注解信息

private static void getAnnotationInfos() {        Student student = new Student("mr.simple");        Test classTest = student.getClass().getAnnotation(Test.class);        System.out.println("class Annotatation tag = " + classTest.tag());        Field field = null;        try {            field = student.getClass().getDeclaredField("mGrade");            Test testAnnotation = field.getAnnotation(Test.class);            System.out.println("属性的 Test 注解 tag : " + testAnnotation.tag());        } catch (Exception e) {            e.printStackTrace();        }    }

   接口说明

// 获取指定类型的注解public  A getAnnotation(Class annotationClass); // 获取 Class 对象中的所有注解public Annotation[] getAnnotations();
 

转载于:https://www.cnblogs.com/krislight1105/p/9999657.html

你可能感兴趣的文章
静态链接与动态链接的区别
查看>>
Android 关于悬浮窗权限的问题
查看>>
如何使用mysql
查看>>
linux下wc命令详解
查看>>
敏捷开发中软件测试团队的职责和产出是什么?
查看>>
在mvc3中使用ffmpeg对上传视频进行截图和转换格式
查看>>
python的字符串内建函数
查看>>
Spring - DI
查看>>
微软自己的官网介绍 SSL 参数相关
查看>>
Composite UI Application Block (CAB) 概念和术语
查看>>
64位MATLAB和C混合编程以及联合调试
查看>>
原生js大总结二
查看>>
PHP基础
查看>>
UVa 11488 超级前缀集合(Trie的应用)
查看>>
Django 翻译与 LANGUAGE_CODE
查看>>
[转]iOS教程:SQLite的创建数据库,表,插入查看数据
查看>>
【转载】OmniGraffle (一)从工具栏开始
查看>>
初识ionic
查看>>
java 中打印调用栈
查看>>
开发 笔记
查看>>