• 跟着刚哥梳理java知识点——反射和代理(十七)


    反射机制是什么?
    反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有的属性和方法
    ;对于任意一个对象,都能够调用他的一个方法和属性,这种动态获取的信息以及
    动态调用对象的方法的功能称为java语言的反射机制。

    反射机制能做什么?
     反射机制主要提供以下功能
      √ 在运行时判断任意一个对象所属的类
      √ 在运行时构造任意一个类的对象
      √ 在运行时判断任意一个类所具有的的属性和方法
      √ 在运行时调用一个对象的方法
      √ 生成动态代理

    通过一个对象获得完整的包名和类名

    package com.hzg;
    public class TestReflect {
        public static void main(String[] args) throws Exception {
            TestReflect testReflect = new TestReflect();
            System.out.println(testReflect.getClass().getName());
            // 结果 com.hzg.TestReflect
        }
    }

    通过一个对象获得完整的属性、方法

    Class clazz = Person.class();
    //1、创建clazz对象的运行时类Person对象
    Person p = (Person)clazz.getInstance();
    //2、通过反射调用运行时的指定属性
    Filed f1 = clazz.getField("name");
    f1.set(p,"LiudeHua");
    //3、通过反射调用运行时的指定的方法
    Method m1 = clazz.getMethod("show",String.class);
    m1.invoke(p,"CHN");

    注意:Class可不是关键字class,Class是类名字,class是个关键字标识是类

    获取class的实例(3种方式)
      ①调用运行时类本身的.class属性
        Class clazz = Person.class;
      ②通过运行时类的对象获取
        Person p = new Person();
        Class clazz = p.getClass();
      ③通过class的静态方法获取
        Class clazz = Class.forName("com.hzg.TestReflect");

    package com.hzg;
    public class TestReflect {
        public static void main(String[] args) throws Exception {
            Class<?> class1 = null;
            Class<?> class2 = null;
            Class<?> class3 = null;
            // ① 静态方法(一般采用这种形式)
            class1 = Class.forName("com.hzg.TestReflect");
            // ② 运行时类的对象获取
            class2 = new TestReflect().getClass();
            // ③ 类本身.class属性
            class3 = TestReflect.class;
            System.out.println("类名称   " + class1.getName());
            System.out.println("类名称   " + class2.getName());
            System.out.println("类名称   " + class3.getName());
        }
    }    

    获取一个对象的父类与实现的接口

     1 package com.hzg;
     2 import java.io.Serializable;
     3 public class TestReflect implements Serializable {
     4     private static final long serialVersionUID = -2862585049955236662L;
     5     public static void main(String[] args) throws Exception {
     6         Class<?> clazz = Class.forName("com.hzg.TestReflect");
     7         // 取得父类
     8         Class<?> parentClass = clazz.getSuperclass();
     9         System.out.println("clazz的父类为:" + parentClass.getName());
    10         // clazz的父类为: java.lang.Object
    11         // 获取所有的接口
    12         Class<?> intes[] = clazz.getInterfaces();
    13         System.out.println("clazz实现的接口有:");
    14         for (int i = 0; i < intes.length; i++) {
    15             System.out.println((i + 1) + ":" + intes[i].getName());
    16         }
    17     }
    18 }

    有了class实例以后,可以做什么呢?
      ① 可以创建对应运行时类的对象
      ② 获取对应运行是类的完整的类的结构:属性、方法、构造器、包、泛型、注解、异常、内部类。
        如 Method[] m1 = clazz.getMethods():获取类和父类的所有public方法
        Method[] m1 = clazz.getDeclaredMethods():所有修饰符方法
        但是不含父类,只有这个类的中所有修饰符方法
      ③ 调用运行是类中指定的结构(属性、方法、构造器)
        √ 获取指定属性:Field name = clazz.getField("name");
        √ 设置指定public属性:name.set(p,"hzg");
        √ 设置指定private属性:
          Field name = clazz.geDeclaredtField("name");
          name.setAccessible(true);
          name.set(p,"hzg");
        √ 获取指定的方法:Method m1 = clazz.getMethod("show");
        √ 调用指定的方法:
          Object obj = m1.invoke(p); 返回类型就是方法的返回类型

        √ 调用静态方法:m1.invoke(Person.class);
        √ 调用带参数的指定方法:
          Method m1 = clazz.getDeclatedMethod("show1",String.class);
          Object obj = m1.invoke(p,"hzg");

        √ 调用构造器:Constructor con = clazz.getDeclaredConstructor();
        √ 调用带参数构造器,和带参数方法一致

    Java反射的应用---代理

    1、静态代理(基于接口的多态性实现的静态代理)

     1 interface ClothFactory{
     2   void productCloth();
     3 }
     4 //被代理类
     5 class NikeClothFactory implements ClothFactory{
     6   @Override
     7   public void productCloth(){
     8     sysytem.out.printLn("NIKE工厂生产一批衣服");
     9   }
    10 }
    11 //代理类
    12 class ProxyFactory implements ClothFactory{
    13   ClothFactory cf;
    14   public ProxyFactory(ClothFactory cf){
    15     this.cf = cf;
    16   }
    17   @Override
    18   public void productCloth(){
    19     sysytem.out.printLn("代理类开始执行,收代理费1000");
    20     cf.productCloth();
    21   }
    22 }
    23 
    24 public class Test{
    25   public static void main(String[] args){
    26     //① 创建一个被代理对象
    27     NikeClothFactory nike = new NikeClothFactory ();
    28     //② 创建一个代理类对象
    29     ProxyFactory proxy = new ProxyFactory(nike);
    30     //③ 调用代理类对象的方法
    31     proxy.productCloth();
    32   }
    33 }

    静态代理总结:
    ① 代理类和被代理类都实现同一个接口
    ② 代理类和被代理类都实现接口中的方法
    缺点:每个被代理类都需要一个代理类来完成,这样程序需要过多的代理,思考:是否能有一个万能的代理类完成全部的代理功能?

    2、动态代理(基于反射实现的动态代理)

     1 interface ClothFactory{
     2   void productCloth();
     3 }
     4 //被代理类
     5 class NikeClothFactory inplements ClothFactory{
     6   @Override
     7   public void productCloth(){
     8     sysytem.out.printLn("NIKE工厂生产一批衣服");
     9   }
    10 }
    11 //①必须实现InvocationHandler接口
    12 class MyInvocationHandler implements InvocationHandler{
    13   //② 声明接口的代理类
    14   Object obj;
    15   //③ 创建一个方法实例化代理类
    16   public Object bind(Object obj){
    17     this.obj = obj;
    18     return Proxy.newProxyInstance(
    19     obj.getClass().geyClassLoder(),
    20     obj.getClass().getInterfaces(),this);
    21   }
    22   //④ 实现接口InvacationHandler的方法
    23   // 此方法实现:当调用代理类的对象方法的时候,都会转换到它上调用
    24   @Override
    25   public Object invoke(Object proxy,Method method,Object[] args){
    26     Object returnVal = method.invoke(obj,args);
    27     return returnVal();
    28   }
    29 }
    30 //调用实现一下
    31 public class Test{
    32   public static void main(String[] args){
    33     //① 老规矩:创建一个被代理对象
    34     NikeClothFactory nike = new NikeClothFactory ();
    35     //②老规矩:创建一个代理类对象
    36     MyInvocationHandler hander = new MyinvocationHanlder();
    37     ClothFactory proxyCloth = (ClothFactory)hander.bind(nike);
    38     //③ 老规矩:调用代理类对象的方法
    39     proxyCloth .productCloth();
    40   }
    41 }
  • 相关阅读:
    HSSFSheet XSSFWorkbook SXSSF Java读取Excel数据
    js 获取相同name元素的属性值
    jsp 页面返回、本页面刷新
    Spring MVC启动过程(1):ContextLoaderListener初始化
    eclipse中无法查看引用的jar包源码
    eclipse添加tomcat服务器
    PLsql链接oracle配置
    JDK 与TOMCAT的安装详解
    JSON笔记
    linux系统命令大全
  • 原文地址:https://www.cnblogs.com/hzg110/p/6707030.html
Copyright © 2020-2023  润新知