首页 > 代码库 > 跟着刚哥梳理java知识点——反射和代理(十七)

跟着刚哥梳理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.Object11         // 获取所有的接口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   @Override18   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   @Override25   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 }

 

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