Java反射机制以及应用

Java反射机制以及应用

1、Java反射

在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。

2、Java程序运行大致过程

Java源文件(.java文件)–>经过Javac编译器编译–>二进制字节码文件(.class文件)–>Jvm类加载器加载–>解释器解释–>机器码(机器可理解的代码)–>操作系统平台

3、Java反射作用以及原理

3.1 反射作用

通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

3.2 反射原理

简单来说就是通过反编译,来获取类对象的属性、方法等信息。
Java的反射机制是在编译时并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用的是在编译期并不知道的类。

反编译:.class–>.java

注意:Jvm从本地磁盘把字节码文件加载到Jvm内存中,Jvm会自动创建一个class对象。即一个类只会产生一个class对象。
原因:类加载机制–双亲委派机制

4、类加载机制–双亲委派机制

JVM中提供了三层的ClassLoader:

  • BootstrapClassLoader:主要负责加载核心的类库(java.lang.*等),构造ExtClassLoader和APPClassLoader。

  • ExtClassLoader:主要负责加载jre/lib/ext目录下的一些扩展的jar。

  • AppClassLoader:主要负责加载应用程序的主函数类。

双亲委派机制下类加载过程如图:

在这里插入图片描述

在考虑存在自定义类加载器情况下,对类的加载首先是从自定义类加载器中检查该类是否已经被加载过,如果没有被加载,则向上委托,拿到父类构造器AppClassLoader加载器进行检查,如果还是没有被加载,则依次向上委托,不断检查父类加载器是否已经加载过该类。如果已经加载,则无需进行二次加载,直接返回。如果经过BootstrapClassLoader加载器检查后,发现该类未被加载,则从父类向下开始加载该类。如果BootstrapClassLoader加载器无法加载该类,则交由子类加载器加载,依次向下加载。

双亲委派机制的作用:

  • 避免相同类二次加载
  • 防止核心类库API被修改

5、Java反射使用

5.1 获取类对象的三种方式

  • 通过Class类中的静态方法forName,来获取类对象
Class clazz1 = Class.forName("全限定类名");
  • 通过类名.class
Class clazz2  = Demo.class;
  • 通过类的实例获取该类的字节码文件对象
Class clazz3 = p.getClass();

5.2 反射获取类属性、方法、构造方法

public class TargetDemo {

    public TargetDemo (){}

    public TargetDemo (String str){
        this.str = str;
        System.out.println("执行构造器方法");
    }

    public String str = "hello";

    private String username;

    private int age;

    public void print(){
        System.out.println("TargetDemo");
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

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

    public static void main(String[] args) {
        try {
            //获取类对象
            Class<?> target = Class.forName("com.torlesse.consumer.test.TargetDemo");
            //获取类对象属性  公共部分不能访问私有
            for (Field field : target.getFields()) {
                System.out.println(field.getName());
            }

            //获取构造器
            Constructor<?> targetDeclaredConstructor = target.getDeclaredConstructor(String.class);
            Object o = targetDeclaredConstructor.newInstance("demo");
            System.out.println(o);

            //实例化对象
            Object o1 = target.newInstance();
            //获取方法
            Method method = target.getMethod("print");
            method.invoke(o1,null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果:
在这里插入图片描述

6、运行指定包下获取被指定注解的类

方案使用:reflections框架
依赖导入:

<dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.11</version>
        </dependency>

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
        </dependency>
//标记类注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JobClassInterface {

}
//标记方法的注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)

@Documented
public @interface JobMethodInterface {
    String jobName();

}
//入参 要扫描的包名
Reflections f = new Reflections("com.torlesse.xxx.xxx");

//入参 目标注解类
Set<Class<?>> set = f.getTypesAnnotatedWith(JobClassInterface.class);

Iterator<Class<?>> iterator = set.iterator();
while (iterator.hasNext()){
   Class<?> next = iterator.next();
   for (Method method : next.getMethods()) {
   for (Annotation declaredAnnotation : method.getDeclaredAnnotations()) {
       if(declaredAnnotation instanceof JobMethodInterface){
           String targetName = ((JobMethodInterface)declaredAnnotation).jobName();
           if(targetName.equals(jobName)){
                method.invoke(next.newInstance(), null);
                return;
                }
             }
       }
   }
}

Java反射机制及应用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TorlesseLiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值