javaSE之反射技术

java反射技术

什么是反射技术

1.java反射机制的核心是在程序运行时动态加载类并获取类的的详细信息,从而获取对象的各种信息.
2.java属于先编译后运行的语言,程序中对象的类型在编译时期就定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以就没有被加载到jvm,通过反射,可以在运行时动态的创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁.

  • java单设机制l可以动态方式获取class相关信息,class中成员方法,属性,反射技术灵活调用方法,或者给我们的成员属性赋值.class.forName 初始化对象(创建对象)
  • 图解
    在这里插入图片描述

简单回顾双亲委派机制

当一个类加载器收到了类加载的请求时,他不会直接去加载指定的类,而是把这个请求委托给自己的父类加载器去加载,只有当父类加载器无法加载这个类的时候,才会由当前这个加载器来负责类的加载.

  • 启动(Bootstrap) ClassLoader(启动类加载器):主要负责加载java核心类库,%JRE_HOME%\bin下的rt.jar,resources.jar,charsets.jar和class等.
  • Extention ClassLoader(扩展类加载器):主要负责加载java核心类库,%JRE_HOME%\lib\ext目录下的jar包和class文件.
  • Application ClassLoader(应用程序类加载器):主要负责加载当前应用的classpath下的所有类
  • User ClassLoader(应用程序类加载器):主要负责当前应用的classpath下的所有类
  • 这四种类加载器存在如下关系,当进行类加载器的时候,虽然用户自定义类不会由bootstrap classloader或是extention classloader加载(由类加载器的加载范围决定),但是代码实现还是会一直委托到bootstrap classloader,上层无法加载,再由下层决定是否可以加载,如果都无法加载,就会触发findclass,抛出classNotFoundException
    在这里插入图片描述
  • 意义:
    1.通过双亲委派的方式,可以避免类的重复加载,当父类加载器已经加载过某一个子类时,只会加载JAVA_HOME中的jar包里的类,如java.long.integer,那么这个类是不会被随意替换的,除非有人抛到你的机器上,破坏你的JDK.那么就可以避免有人自定义一个有破坏功能的java.long.Integer被加载.这样可以有效防止核心Java API被篡改.

反射的优缺点

  • 优点:在运行时获取类的各种内容,进行反编译,对于java这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象.
  • 缺点:
    1.反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要反射.
    2.反射调用方法时可以忽略权限检查,因此可能会破坏封装性而导致安全问题.

反射机制应用场景

  • JDBC中的Class.forName(“包名.类名”)
  • Spring底层基于反射初始化对象
  • 第三方框架扩展功能

反射机制核心类

  • java.lang.Class :代表正在运行的java类或接口
  • java.lang.reflect.Constructor
  • java.lang.reflect.Field
  • java.lang.reflrct.Method
  • java.lang.reflect.Modifier

反射机制API使用

获取Class

1.获取Class:三种方式:
1)Object---->getClass
2)任何数据类型(包括基本的数据类型)都有一个"静态"的class属性
3)通过class类的静态方法:forName(String className)常用
参数:全限定名称

public class ReflexTest {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, 
    IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        //反射技术创建对象
        Class<?> aClass = Class.forName("com.Reflex");
        //创建对象
        Reflex r = (Reflex) aClass.newInstance();
        System.out.println(r);
        //通过反射走有参构造方法
        Constructor<?> constructor = aClass.getConstructor(String.class,int.class);
        Reflex r1= (Reflex) constructor.newInstance("蔡徐坤", 23);//获取所有共有构造方法
        System.out.println(r1);

    }
}

获取成员属性

  • 批量的
    1.Field[ ] getFields():获取所有"公开子段"
    2.Field[] getDeclaerDield():获取所有子段,包括:私有,保护,默认,公有;
  • 单个的
    1.public Field getField(String fieldName):获取某个"公有的"子段
    2.public Field getDeclaredField(String fieldName):获取某个子段(可以是私有的)
  • 设置子段的值
    1.Field---->public void set(Object obj,Object value):
import java.lang.reflect.Field;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException, 
            NoSuchFieldException, InstantiationException, IllegalAccessException {
        //获取class成员属性(反射给成员属性赋值,反射调用方法)
        //反射技术创建对象
        Class<?> aClass = Class.forName("com.Reflex");
        Field[] fields = aClass.getFields();//获取所有共有字段
        for (Field field : fields) {
            System.out.println(field);
        }
        Field[] declaredFields = aClass.getDeclaredFields();//获取所有字段
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //给成员属性赋值
        Reflex reflex = (Reflex) aClass.newInstance();
        Field name = aClass.getDeclaredField("name");
        //通过反射给成员属性赋值,先设置权限
        //抑制java语言检查功能
        name.setAccessible(true);
        name.set(reflex,"蔡训坤");
        System.out.println(reflex.getName());
    }
}

反射获取成员方法

  • 所有的方法
    1.public Method[] getMethods()获取所有"公有方法"(包含父类Object类)
    2.获取单个方法:
    1.public Method getMethod(String name.Class)<?>...parameter(Types): 参数: name 方法名 Class...:形参的Class类型对象 public Method getDeclaerdMethod(String name,Class<?>…parameterTypes)
public class Test1 {
    private static Object Reflex;

    public static void main(String[] args) throws ClassNotFoundException, 
            NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        Class<?> aClass = Class.forName("com.Reflex");
        //输出所有共有方法
        Method[] methods = aClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        //获取所有方法不能获取Object
        Method[] declaredMethods = aClass.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
        //给私有方法赋值
        Method show = aClass.getDeclaredMethod("show", String.class, int.class);
        //创建实例
        Reflex reflex = (Reflex) aClass.newInstance();
        show.setAccessible(true);
        String str=(String) show.invoke(reflex,"蔡训坤",23);
        System.out.println(str);
    }
}

反射的应用

1.ArraryList里面如何添加字符串
2.读取.properties文件的方式,让程序更加灵活

反射----jdk动态代理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值