反射

作者: vv_64ce | 来源:发表于2020-04-18 17:17 被阅读0次

反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息,并直接操作任意对象的内部属性和方法


图片.png 反射的功能 图片.png java.lang.Class类的加载理解
1.类的加载过程:

程序经过javac.exe命令后,会生成一个或多个字节码文件(.class结尾);接着我们使用java.exe命令对某个字节码文件进行解释运行,相当于将某个字节码文件加载到内存中,此过程称为类的加载。加载到内存中的类,称为运行时类,此时运行时类,就作为Class的一个实例
2.换句话说,Class的实例就对应着一个运行时类
3.加载到内存中的运行时类,会缓存一定的时间。在此时间之内,可以沟通过不同方式获取此运行时类

获取Class的实例的方式(掌握三种)
public class ReflectPerson {
    @Test
    public void test01() throws ClassNotFoundException {
        //方式一:调用运行时类的属性,.class(掌握)
        Class<Person> clazz1 = Person.class;
        System.out.println(clazz1);

        //方式二:通过运行时类的对象,调用getClass()(掌握)
        Person p = new Person();
        Class<? extends Person> clazz2 = p.getClass();
        System.out.println(clazz2);

        //方式三:调用Class的静态方法,forName(String classPath)((掌握)使用频率高)
        Class<?> clazz3 = Class.forName("com.vv.reflect.Person");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz3 == clazz2);

        //方式四:使用类的加载器,ClassLoader(了解)
        ClassLoader loader = ReflectPerson.class.getClassLoader();
        Class<?> clazz4 = loader.loadClass("com.vv.reflect.Person");
        System.out.println(clazz4);
    }
}
可以有Class对象的类型 举例: Class对象的类型
类的加载过程 解释类的加载过程 类的加载过程举例

读取配置文件:

 @Test
    public void test01() throws IOException {
        Properties pro = new Properties();
        //读取配置文件方式一:默认当前project下
        //读取文件
        FileInputStream fis = new FileInputStream("src\\db1.properties");
        //加载文件
        pro.load(fis);

//        //读取配置文件方式二:文件默认识别为当前moudle的src下
//        InputStream is = Propeties01.class.getClassLoader().getResourceAsStream("db1.properties");
//        pro.load(is);

        String name = pro.getProperty("name");
        String age = pro.getProperty("age");
        System.out.println(name+"......"+age);
    }

通过反射运行时的类获得其属性、方法、构造器

@Test
    public void field() throws Exception {
        //1.创建Class的对象
        Class<Person> clazz = Person.class;
        //2.创建该对象的实例,便于调用对象的属性、方法、构造器
        Person person = clazz.newInstance();

        //3.获得该属性
        Field name = clazz.getDeclaredField("name");
        //4.保证当前属性是可访问的
        name.setAccessible(true);
        //5.获取、设置指定对象的此属性值
        name.set(person,"张三");
        System.out.println(name.get(person));
    }
    @Test
    public void method() throws Exception {
        Class clazz = Person.class;
        Person p = (Person) clazz.newInstance();
        Method declaredMethod = clazz.getDeclaredMethod("showTime",int.class);
        declaredMethod.setAccessible(true);
        //调用的invoke():参数1:方法的调用者  参数2:给方法形参赋值的实参
        // invoke()的返回值即为对应勒种调用方法的返回值
        Object o = declaredMethod.invoke(p, 12);
        System.out.println(o);

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

        //静态方法的调用,不需要在进行创建对象
        Method staticTest = clazz.getDeclaredMethod("staticTest");
        staticTest.setAccessible(true);
        //调用的invoke方法没有返回值时,参数可以为null
        staticTest.invoke(clazz);// staticTest.invoke(null);

    }
    @Test
    public void constructor() throws Exception {
        Class clazz = Person.class;
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        Object instance = declaredConstructor.newInstance("张三", 13);
        System.out.println(instance);
    }
反射的应用:动态代理
public class ProxyTest {

   @Test
   public void test(){
       Man man = new Man();
       Human proxyInstance = (Human) ProxyFactory.getProxyInstance(man);
       proxyInstance.breath();
       proxyInstance.eat("苹果");

   }
}
interface Human{
   void breath();
   void eat(String food);
}
//被代理类
class Man implements Human{

   @Override
   public void breath() {
       System.out.println("Man呼吸新鲜空气");
   }

   @Override
   public void eat(String food) {
       System.out.println("Man吃"+food);
   }
}
/*
要想创建动态代理:
1.如何根据加载到内存中的被代理类,动态创建一个代理类及对象
2.当通过代理类的对象调用方法时,如何动态调用被代理类中的同名方法
*/
class ProxyFactory{

   //创建动态代理,
   //解决一:调用此方法,返回一个代理类对象Object;参数Object obj是被代理类的对象
   public static Object getProxyInstance(Object obj){
       //创建Handler对象
       MyInvocatoinHandler handler = new MyInvocatoinHandler();
       handler.bind(obj);
       //参数一:被代理类的类的加载器  参数二:被代理类的接口 参数三:调用代理类中的同名方法
       return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),handler);
   }


}
//实现InvocationHandler接口
class MyInvocatoinHandler implements InvocationHandler{
   private Object obj;//需要使用被代理对象进行赋值
   public void bind(Object obj){
       this.obj = obj;
   };
   //Object proxy:动态代理的对象
   //Method method:调用的反射类中的方法
   //Object[] args:method中的参数
   //Object返回值类型是method方法中的返回值类型
   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //被代理类的执行方法功能声明
       return method.invoke(obj,args);

   }
}
动态代理和AOP
图片.png

相关文章

  • Java基础之反射

    Java基础之反射 反射基本介绍 反射的使用通过反射调用属性和方法通过反射获取配置文件 反射基本介绍 Java反射...

  • 镜面反射矩阵的推导

    镜面反射是以镜面作为反射平面,实物与反射物到反射平面的距离相等,实物与反射物方向相反,所以,反射矩阵由反射平面确定...

  • reflect.go包学习_之二 指针操作提高反射性能 反射应用

    reflect.go包学习_之二 指针操作提高反射性能 反射应用 反射创建实例 反射信息、反射调用方法、反射修改值...

  • Java互联网公司-经典面试题附答案

    基础:Java 反射?反射有什么缺点?你是怎么理解反射的(为什么框架需要反射)?优点:反射具有解耦性,缺点:反射属...

  • Java反射与joor反射库的使用

    java原生反射的使用 反射构造对象 反射方法 反射字段 joor反射库的使用 github:https://gi...

  • Java反射

    什么是反射? 反射的作用? 反射性能优化?

  • 反射三定律

    反射第一定律:反射可以将interface类型变量转换成反射对象 反射第二定律:反射可以将反射对象还原成inter...

  • 反射

    1.反射是什么?反射的定义,概念 2.为什么要学反射? 3.怎么使用反射?反射的使用

  • 一周岁前做好两件事,孩子就不会语言迟缓,保证口齿伶俐

    与语言发展相关的原始反射有四个:张口反射、足跖反射、抓握反射和手拉反射,每个反射的发生、发展和整合都是次第进行的,...

  • 面试官问go反射第一弹

    目录 反射概念 reflect包 反射类型(Type)和种类(Kind) 反射类型(Type)使用 反射类型对象(...

网友评论

      本文标题:反射

      本文链接:https://www.haomeiwen.com/subject/dgamvhtx.html