回顾Java反射

如果你不相信努力和时光,那么成果就会是第一个选择辜负你的。不要去否定你自己的过去,也不要用你的过去牵扯你现在的努力和对未来的展望。不是因为拥有希望你才去努力,而是去努力了,你才有可能看到希望的光芒。回顾Java反射,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Java中的反射可以在程序运行期动态的获取程序信息。

关于反射,从下面的这段话仔细揣摩。

java.lang.reflect 库中包含类 Field、Method 和 Constructor(每一个都实现了 Member 接口)。这些类型的对象由 JVM 在运行时创建,以表示未知类中的对应成员。然后,可以使用 Constructor 创建新对象,get() 和 set() 方法读取和修改与 Field 对象关联的字段,invoke() 方法调用与 Method 对象关联的方法。此外,还可以调用便利方法 getFields()、getMethods()、getConstructors() 等,以返回表示字段、方法和构造函数的对象数组。(你可以通过在 JDK 文档中查找类 Class 来了解更多信息。)因此,匿名对象的类信息可以在运行时完全确定,编译时不需要知道任何信息。

这段文字摘自github上面的 Java编程思想

依我个人而言,反射就是一种技术,从Java的角度看,这种技术可以在程序的运行期获得对象的类信息和属性信息,结合面向接口编程,相同的接口引用指向不同的对象,只要拿到对象就可以拿到类里面的成员变量和成员方法,拿到方法后可以调用方法,拿到字段后可以设置字段的值

反射代码

使用反射得到类的访问修饰符,包名,类名以及判断类的属性:

 public static void main(String[] args) {
          Class clazz = TempTest.class;
          //获取访问修饰符
          int modify = clazz.getModifiers();
          System.out.println(Modifier.toString(modify));

          //获取包名和全限定类名
          Package p = clazz.getPackage();
          String name = clazz.getName();
          System.out.println("p : "+p+" \nname : "+name);

          System.out.println("isInterface(): "+clazz.isInterface());
          System.out.println("isEnum(): "+clazz.isEnum());
          System.out.println("isAnnotation(): "+clazz.isAnnotation());
          System.out.println("isArray(): "+clazz.isArray());
}

获取构造器对象,然后使用构造器对象创建实例

	  Class<?> clazz = Class.forName("com.llm.test.TempTest");
      //使用Class对象创建对象(默认是使用的无参构造方法)
      TempTest tem = (TempTest)clazz.newInstance();

      Constructor<?>[] cons = clazz.getDeclaredConstructors();
      for (int i = 0; i < cons.length; i++) {
           System.out.println(cons[i]);
      }
      Constructor<?> constructor = clazz.getConstructor();

      Object o = constructor.newInstance();
      System.out.println(o);

使用反射操作对象的方法

public static void main(String[] args) throws Exception {
          Class clazz = Student.class;
          //利用默认空参实例化一个对象
          Student stu = (Student)clazz.newInstance();

          //公有方法
          Method m = clazz.getMethod("sleep");
          m.invoke(stu,null);

          //私有方法
          Method m2 = clazz.getDeclaredMethod("run");
          m2.setAccessible(true); //不加的话报 IllegalAccessException
          m2.invoke(stu,null);

          //静态方法
          Method m3 = clazz.getDeclaredMethod("play");
          m3.invoke(null); //静态方法不需要对象就可以调用
     }

     static class Student{
          public void sleep(){
               System.out.println("sleep() ");
          }
          private void run(){
               System.out.println("run() ");
          }
          public static void play(){
               System.out.println("static::play() ");
          }
     }

反射操作成员变量

public static void main(String[] args) throws Exception {

          Class clazz = Student.class;
          Student stu = (Student)clazz.newInstance();

          System.out.println("获取public属性,并设置值");
          Field name = clazz.getField("name");
          name.set(stu,"小李");
          System.out.println(stu);

          System.out.println("获取private属性,并设置值");
          Field age = clazz.getDeclaredField("age");
          age.setAccessible(true); // 不加这一行会报 IllegalArgumentException
          age.set(stu,20);
          System.out.println(stu);

          System.out.println("获取静态属性,并设置值");
          Field password = clazz.getField("password");
          password.set(stu,"123");
          System.out.println(Student.password);
     }

     static class Student{
          private int age;
          public String name;
          public static String password;

          @Override
          public String toString() {
               return "Student{" +
                       "age=" + age +
                       ", name='" + name + '\'' +
                       '}';
          }

          public int getAge() {
               return age;
          }

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

          public String getName() {
               return name;
          }

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

          public static String getPassword() {
               return password;
          }

          public static void setPassword(String password) {
               Student.password = password;
          }
     }

反射配合注解使用

反射最常用的技术可能就是搭配注解来做一些功能了,使用反射,可以使标注指定注解的类实现一些特别的功能

在研究反射配置注解的操作之前,可以先看一看如何自定义注解

自定义注解里面的参数可以设置为:
(String,数组,枚举,基本数据类型,Class类型)

下面结合注解和反射,可以完成一个简单的属性注入的功能

  1. 首先定义注解MyAnnotation
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyAnnotation {
    String name();
    int[] ages() default {0};
    Gender man() default Gender.MAN;
    int age();
    Class clazz() default Integer.class;
}

enum Gender{
    MAN,WOMAN
}
  1. 然后再创建一个类Student 来测试操作:
public class Student {

    private String name;
    private int age;

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

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

    @MyAnnotation(name = "张三",age = 19)
    public void print(){
        System.out.println("我的名字是: "+name+" 我的年龄是:"+age);
    }
}
  1. 最后是使用反射的操作类:
public class AnnotationTest {

    public static void main(String[] args) throws Exception {
        Class clazz = Student.class;
        //获取所有的方法
        Method[] methods = clazz.getDeclaredMethods();
        MyAnnotation annotation = null;
        for (Method m :
                methods) {
            if (m.isAnnotationPresent(MyAnnotation.class)){
                annotation = m.getAnnotation(MyAnnotation.class);
            }
        }
        if (annotation == null){
            System.err.println("没有找到目标注解:");
            return;
        }
        int age = annotation.age();
        String name = annotation.name();

        System.out.println("使用实例化开始设置值,然后调用print()方法");
        Student o = (Student)clazz.newInstance();
        o.setAge(age);
        o.setName(name);
        o.print();
    }

}

完成了上面这三步,就可以实现把注解上的参数注入到指定的对象的操作。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/202482.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!