java反射机制怎么实现

蜗牛 互联网技术资讯 2022-11-10 89 0

这篇文章主要介绍“java反射机制怎么实现”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“java反射机制怎么实现”文章能帮助大家解决问题。

  1.获取Class对象的三种方式

1. 通过对象的getClass()方法
Class c1=(new User()).getClass();

2. 通过字节码文件获取
Class c2=User.class;

3. 通过Class类的静态方法获取
Class c3=Class.forName("com.bee.entity.User");
  1. 同一个类只会被加载一次

public class Test {

  public static void main(String[] args) {
    String path = "demo6.TestBean";
    try {
      Class<?> clazz1 = Class.forName(path);
      System.out.println(clazz1.hashCode());

      Class<?> class2 = Class.forName(path);
      System.out.println(class2.hashCode());

    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

输出

366712642
366712642

Class对象专门用来存放类的信息。一个类只对应一个Class对象。因为,类的对象虽然可以有多个,但对应的类只有一个。

  1. 利用反射获取类的信息

先定义一个类TestBean

public class TestBean {
  private String name;
  private int age;

  public TestBean() {
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }

  public TestBean(String name, int age) {
    super();
    this.name = name;
    this.age = age;
  }
}

读取上述类TestBean的信息

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {

  public static void main(String[] args) {
    String path = "demo.TestBean";
    try {
      Class<?> clazz = Class.forName(path);

      // 获取类的名字
      System.out.println(clazz.getName()); // 获得包全路径名
      System.out.println(clazz.getSimpleName()); // 只获得类名

      // 获取属性信息
      Field[] fields1 = clazz.getFields(); // 只能获取public属性
      Field[] fields2 = clazz.getDeclaredFields(); // 可以获得private属性(可以获得所有的属性)
      Field field3 = clazz.getDeclaredField("name");
      for (Field field : fields2) {
        System.out.println("属性:" + field);
      }

      // 获取方法信息
      // clazz.getMethod(name, parameterTypes) 只能获得public方法
      Method[] methods = clazz.getDeclaredMethods();
      Method method1 = clazz.getDeclaredMethod("getName", null);
      // 如果方法有参数,必须传递参数类型对应的Class对象。
      Method method2 = clazz.getDeclaredMethod("setName", String.class);
      for (Method method : methods) {
        System.out.println("方法:" + method);
      }

      // 获得构造器信息
      // Constructor[] constructors=clazz.getConstructors() 只能获得public构造方法
      Constructor[] constructors = clazz.getDeclaredConstructors();
      for (Constructor constructor : constructors) {
        System.out.println("构造器:" + constructor);
      }
      // 获取无参构造器
      Constructor cons1 = clazz.getDeclaredConstructor(null);
      System.out.println("无参构造器:" + cons1);
      // 获取有参构造器
      Constructor cons2 = clazz.getDeclaredConstructor(String.class, int.class);
      System.out.println("有参构造器:" + cons2);

    } catch (Exception e) {
      e.printStackTrace();
    }

  }

}
  1. 通过反射动态操作构造器,方法,属性

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {

  public static void main(String[] args) {
    String path = "demo.TestBean";
    try {
      Class<TestBean> clazz = (Class<TestBean>) Class.forName(path);

      // 通过反射构造对象
      TestBean tb = clazz.newInstance(); // 调用TestBean的无参构造方法
      // 对于JavaBean/POJO/DTO必须要配置一个无参构造器,以便框架使用newInstance()构建对象实例。
      System.out.println(tb);

      // 调用有参构造器
      Constructor<TestBean> cons1 = clazz.getDeclaredConstructor(String.class, int.class);
      TestBean tb1 = cons1.newInstance("黄忠", 83);
      System.out.println(tb1.getName() + tb1.getAge() + "岁");

      // 通过反射调用普通方法
      TestBean tb2 = clazz.newInstance();
      tb2.setName("云长"); // 等效于下边的invoke()方法
      tb2.setAge(57); // 等效于下边的invoke()方法

      TestBean tb3 = clazz.newInstance();
      Method method1 = clazz.getDeclaredMethod("setName", String.class);
      Method method2 = clazz.getDeclaredMethod("setAge", int.class);
      method1.invoke(tb3, "玄德");
      method2.invoke(tb3, 66);
      System.out.println(tb3.getName() + tb3.getAge() + "岁");

      // 通过反射操作属性
      TestBean tb4 = clazz.newInstance();
      Field f1 = clazz.getDeclaredField("name");
      Field f2 = clazz.getDeclaredField("age");

      // 报错不能访问私有属性的解决方法(属性可以设置,方法也可以这样设置)
      f1.setAccessible(true);
      f2.setAccessible(true);

      f1.set(tb4, "紫龙");
      f2.set(tb4, 33);
      System.out.println(tb4.getName() + f2.get(tb4) + "岁");

    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}
  1. 反射机制的性能

  • setAccessible

  1. 是访问安全检查的开关。设置true表示反射的对象在使用时应该取消Java语言访问检查。

  2. 禁止安全检查可以提高反射的运行速度。

  • 可以考虑使用cglib/javaassist字节码操作提升反射操作的速度。

  1. 反射操作泛型(Generic)

  • Java使用泛型擦除机制来引入泛型。Java中的泛型仅仅是给编译器javac使用的。泛型用于确保数据的安全性和免去强制类型转换带来的不便。Java一旦编译完成,所有和泛型有关的类型将全部擦除。

  • Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型,但又和原始类型保持一致。

  1. ParameterizedType:表示一种参数化的类型,比如:Collection

  2. GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型

  3. TypeVariable:是各种类型变量的公共父接口

  4. WildcardType:代表一种通配符类型表达式,比如:?,? extends Number,? super Integer。

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class Test {

  public void test1(Map<String, TestBean> map, List<TestBean> list) {
    System.out.println("Test.test1()");
  }

  public Map<Integer, TestBean> test2() {
    System.out.println("Test.test2()");
    return null;
  }

  public static void main(String[] args) {
    try {
      // 获得指定方法参数泛型信息
      Method m = Test.class.getMethod("test1", Map.class, List.class);
      Type[] t = m.getGenericParameterTypes();
      for (Type type : t) {
        System.out.println("#" + type);
        if (type instanceof ParameterizedType) {
          Type[] genericTypes = ((ParameterizedType) type).getActualTypeArguments();
          for (Type genericType : genericTypes) {
            System.out.println("泛型类型:" + genericType);
          }
        }
      }

      System.out.println("-------------------");

      // 获得指定方法返回值泛型信息
      Method m2 = Test.class.getMethod("test2", null);
      Type returnType = m2.getGenericReturnType();
      System.out.println("#" + returnType);
      if (returnType instanceof ParameterizedType) {
        Type[] genericTypes = ((ParameterizedType) returnType).getActualTypeArguments();
        for (Type type : genericTypes) {
          System.out.println("返回值泛型类型:" + type);
        }
      }

    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (SecurityException e) {
      e.printStackTrace();
    }

  }

}

关于“java反射机制怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注蜗牛博客行业资讯频道,小编每天都会为大家更新不同的知识点。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

评论

有免费节点资源,我们会通知你!加入纸飞机订阅群

×
天气预报查看日历分享网页手机扫码留言评论Telegram