分享好友 编程语言首页 频道列表

java反射机制怎么实现 java中的反射机制使用

Java教程  2023-02-09 04:140

这篇文章主要介绍“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反射机制怎么实现”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注***行业资讯频道,小编每天都会为大家更新不同的知识点。

查看更多关于【Java教程】的文章

展开全文
相关推荐
反对 0
举报 0
评论 0
图文资讯
热门推荐
优选好物
更多热点专题
更多推荐文章
sf02_选择排序算法Java Python rust 实现
Java 实现package common;public class SimpleArithmetic {/** * 选择排序 * 输入整形数组:a[n] 【4、5、3、7】 * 1. 取数组编号为i(i属于[0 , n-2])的数组值 a[i],即第一重循环 * 2. 假定a[i]为数组a[k](k属于[i,n-1])中的最小值a[min],即执行初始化 min =i

0评论2023-02-09407

JavaScript面向对象轻松入门之抽象(demo by ES5、ES6、TypeScript)
抽象的概念  狭义的抽象,也就是代码里的抽象,就是把一些相关联的业务逻辑分离成属性和方法(行为),这些属性和方法就可以构成一个对象。  这种抽象是为了把难以理解的代码归纳成与现实世界关联的概念,比如小狗这样一个对象:属性可以归纳出“毛色”、

0评论2023-02-09777

Java与Objective-C的渊源 objective-c和c++的区别
java创始成员Patrick Naughton回忆,通常人们会认为Java是学Modula-3和C+,其实这些都是谣传,而对Java影响比较大的则是Objective-C:单 继承、动态绑定和加载、类对象、纯虚函数、反射、原始类型包装类等。Java的接口直接抄自OC的协议。  Objective-C是扩

0评论2023-02-09806

更多推荐