• 反射机制(Reflection)


            java有一定动态性,使用反射可以在程序运行时借助Reflection API获得任何类的信息,并直接改变其中的属性和方法。步骤如下:

    一、获得反射对象的Class对象

            加载完类之后,在方法区就会生成一个class对象,这个对象包含了类的完整信息。

    1. Class c=Class.forName("com.fan.Person");
    2. Class c1=(new Person(1,"ming")).getClass();
    3. Class c2=Person.class;
    4. System.out.println(c.equals(c1));

    Notations:一个类有唯一的Class对象,类的整个结构被封装在这个对象中。一个Class对象对应一个加载到JVM的.class文件。

            除了上面获得Class对象的三种方法,每种内置包装类型都有Type属性。

                    Class c3=Integer.TYPE;

            或获得父类类型:

                    Class c4=c3.getSuperClass();

    二,获取类的完整结构

            类的完整结构包括:Field,Method,Constructor,SuperClass,Interface,Annotation

    1. Class c=Class.forName("com.fan.Person");
    2. // 获得类的名字
    3. System.out.println(c.getName());
    4. System.out.println(c.getSimpleName());
    5. // 获得类的属性(使用getFields的话只能访问public的属性)
    6. Field[] F=c.getDeclaredFields();
    7. for (Field f:F){
    8. System.out.println(f);
    9. }
    10. // 获取类的方法
    11. Method[] M=c.getDeclaredMethods();
    12. for(Method m:M){
    13. System.out.println(m);
    14. }
    15. // 获得指定方法,加上传参的class,因为有方法重载
    16. Method m=c.getDeclaredMethod("setName", String.class);
    17. // 获得指定的构造器
    18. Constructor[] c1=c.getConstructors();

    三,动态创建对象并操作

    1. Class c=Class.forName("com.fan.Person");
    2. // 调用类的无参构造器构造类,类里没有无参构造器就要报错
    3. Person P=(Person)c.newInstance();
    4. // 通过有参数的构造器构造对象
    5. Constructor C=c.getDeclaredConstructor(int.class,String.class);
    6. Person P1=(Person)C.newInstance(5,"clearlove");
    7. // 获取函数并调用
    8. Method setName=c.getDeclaredMethod("setName", String.class);
    9. setName.invoke(P,"shy");
    10. System.out.println(P.getName());
    11. // 操作属性,通过setAccessible取消java访问权限检查
    12. Field name=c.getDeclaredField("name");
    13. name.setAccessible(true);
    14. name.set(P1,"the sky");

    Notations:使用反射调用方法比普通方式慢很多,在反射调用前用setAccessible关闭权限会快一些。

    四、获取泛型信息和注解信息

    (1)获得泛型信息

    1. Method m=Person.class.getDeclaredMethod("test",Map.class);
    2. // 注意这里有很多getTypes方法,要看泛型用在了哪里就调用哪个
    3. Type[] generiticParameters=m.getParameterTypes();
    4. for (Type t:generiticParameters){
    5. System.out.println(t);
    6. // 参数是Map,只获得了Map,需要获得真的泛型参数
    7. //t是一个参数化的类型,强转它获得真实的参数信息
    8. if(t instanceof ParameterizedType){
    9. Type[] actualParameterType=((ParameterizedType) t).getActualTypeArguments();
    10. for (Type a:actualParameterType){
    11. System.out.println(a);
    12. }
    13. }

    (2)获取注解信息

    注解定义和位置如下:

    1. @title("Person")
    2. public class Person {
    3. private int age;
    4. private String name;
    5. public Person(){
    6. this.age=0;
    7. this.name=null;
    8. }
    9. public Person(int age, String name) {
    10. this.age = age;
    11. this.name = name;
    12. }
    13. @title("test")
    14. public void test(Map map){
    15. }
    16. public int getAge() {
    17. return age;
    18. }
    19. public void setAge(int age) {
    20. this.age = age;
    21. }
    22. public String getName() {
    23. return name;
    24. }
    25. public void setName(String name) {
    26. this.name = name;
    27. }
    28. }
    29. @Target({ElementType.METHOD,ElementType.TYPE})
    30. @Retention(RetentionPolicy.RUNTIME)
    31. @interface title{
    32. String value();
    33. }

    主程序中获取注解:

    1. //反射获得注解,这种只得到类上面的注解
    2. Class c=Person.class;
    3. Annotation[] annotations=c.getAnnotations();
    4. for (Annotation a:annotations){
    5. System.out.println(a);
    6. }
    7. // 获得注解中的值,传入注解.class可以获得注解的字节码文件
    8. title t;
    9. t = (title) c.getAnnotation(title.class);
    10. System.out.println(t.value());
    11. // 获得其他位置的注解,方法上的为例
    12. Method m=c.getDeclaredMethod("test",Map.class);
    13. System.out.println(m.getAnnotation(title.class).value());

  • 相关阅读:
    web网页设计期末课程大作业:家乡旅游主题网站设计——河北8页HTML+CSS+JavaScript
    微软在2022年Gartner云计算AI开发者服务魔力象限中被评为“领导者”
    文献学习-5-用于腹腔镜安全的自主控制的基于GMM的启发式决策框架
    谷歌api站长批量翻译工具
    【ROS】RViz、Gazebo和Navigation的关系
    Leetcode 剑指 Offer II 003. 前 n 个数字二进制中 1 的个数
    12个常见idea快捷键
    JAVA 0基础 布尔型
    剑指offer
    Java 浅析线程池ThreadPoolExecutor
  • 原文地址:https://blog.csdn.net/small_py_trade/article/details/126971988