关于Java中反射问题的权威解答,欢迎查阅!

1.反射介绍

  • 在运行阶段,动态获取类的信息和调用类的属性和方法的机制称为反射机制

2.反射的作用

  • 获取对象所属的类(父类,接口)
  • 通过类创建对象
  • 获取对象所有的属性和方法(调用)
  • 创建代理对象

3.反射采用api(java.lang.reflect)

  • Class:包含类中所有的信息
    • 通过类加载器在加载过程中为每一个类创建唯一的class对象。
  • Class创建的三种方式  

//1.类名.class

        Class clz = Apple.class;

        //2.对象.getClass()

        Class clz2 = apple.getClass();

        //3.类的全限定名称(全路径)

        try {

            Class clz3 = Class.forName("test.Apple");

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }
  • 创建对象方式
/**

         * 1.调用无参构造(若没有无参构造,或无参构造没有访问权限则创建失败)

         * 2.接口,抽象类,数组,基本类型创建失败

         */

Apple apple = (Apple) clz.newInstance();

apple.eat();

 

  • Field:  封装了属性对象
//获取属性

        //获取封装指定public属性的field对象

        Field field = clz.getField("weight");

        //System.out.println(field);

        //给属性赋值    apple.setWeight(12);

        //对象  值

        Apple apple = clz.newInstance();

        field.set(apple, 12);

        //获取属性的值

        System.out.println(field.get(apple));

       

       

        //获取所有的public修饰的属性(获取父类的属性)

        /*Field [] fields = clz.getFields();

        System.out.println(Arrays.toString(fields));*/

       

        //获取所有的属性(包含私有的,不能获取父类)

        Field [] fields = clz.getDeclaredFields();

        System.out.println(Arrays.toString(fields));

       

        //获取指定属性(私有的)

        Field f = clz.getDeclaredField("size");

        f.setAccessible(true);

        f.set(apple, 11);

        System.out.println(f.get(apple));

 

  • Method:  封装方法的对象
//1.获取public修饰的指定方法

        //Method method = clz.getMethod("show2");

        Method method2 = clz.getMethod("show", String.class);

        //执行方法的调用

        method2.invoke(apple, "aaaa");

        //2.获取所有的public方法(父类的)

        //clz.getMethods();

        //3.获取所有的方法(私有)

        //clz.getDeclaredMethods();

        //4.获取指定私有方法

        Method method = clz.getDeclaredMethod("show2");

        method.setAccessible(true);

        method.invoke(apple);

 

  • Constructor:  包含了构造方法的信息(class获取)
GetConstructor(Class…paramerType):获取公共的构造方法

GetConstructors():获取公共的所有的构造方法

getDeclaredConstructor(Class…paramerType):该类所有构造方法之一(包含私有的)

getDeclaredConstructors():获取所有的构造方法

//2.获取有参构造

        //获取带有一个String类型参数的构造方法

        Constructor<Apple> constructor = clz.getConstructor(String.class);

        //通过constructor创建对象

        Apple apple = constructor.newInstance("红色");

        //apple.show();

        /*Constructor<Apple> constructor = clz.getConstructor();//无参构造

        Apple apple = constructor.newInstance();

        System.out.println(apple);*/

       

        //获取所有的public构造方法

        /*Constructor[] constructors = clz.getConstructors();

        System.out.println(Arrays.toString(constructors));*/

       

        //获取所有的构造方法(包含私有的)

        /*Constructor<?>[] declaredConstructors = clz.getDeclaredConstructors();

        System.out.println(Arrays.toString(declaredConstructors));*/

       

        //获取指定构造方法

        Constructor<Apple> constructor2 = clz.getDeclaredConstructor(int.class);

        //授权

        constructor2.setAccessible(true);

        Apple apple2 = constructor2.newInstance(1);

        apple2.show();

 

  • 反射的优点和缺点
    • 优点: 灵活性和扩展性,降低了耦合性
    • 缺点:  维护难度大
  • 代理模式
    • 开闭原则: 面向修改关闭,面向扩展开放。
    • 代理模式: java语言23种设计模式。(GOF的<<设计模式>>)
    • 设计模式: 经验,代码的扩展,松耦合。
  • 访问对象另一种方式。给需要操作的真实对象创建代理对象,通过操作代理对象实现对真实对象的使用,可以实现对真实对象内容扩展。
    • 静态代理:  在编译期间,为每一个真实对象的类创建代理类
    • 每一个真实对象的方法都要添加增强。
interface Yulequan{

    void play();

    void kongfu();

}



class LiYiFeng implements Yulequan{



    @Override

    public void play() {

        System.out.println("我不会play");

    }



    @Override

    public void kongfu() {

        System.out.println("我不会kongfu");

    }

   

}



//真实对象类

class BaoQiang implements Yulequan{

    @Override

    public void play() {

        System.out.println("我会play");

    }

    @Override

    public void kongfu() {

        System.out.println("我会kongfu");

    }

}

//代理类

class SongZhe implements Yulequan{

    Yulequan bq;

    public SongZhe(Yulequan bq) {

        this.bq = bq;

    }

    @Override

    public void play() {

        System.out.println("开始");

        bq.play();

        System.out.println("结束");

    }

    @Override

    public void kongfu() {

        System.out.println("开始");

        bq.kongfu();

        System.out.println("结束");

    }

}





public class StaticProxy {



    public static void main(String[] args) {

        Yulequan yl = new SongZhe(new LiYiFeng());

        yl.kongfu();

    }



}
  • 动态代理:运行期间,为真实对象创建代理对象的方式。(反射)
    • JDK的动态代理(接口+真正对象的类)
//1.创建目标类对象

       YuLeQuan yl = new BQ();

      

       //2.给目标对象创建代理对象

           //2.1 目标类对象实现同一个接口

           //2.2 代理类对象中需要获取每一个方法

         

       /*参数:  1.类加载器(用于加载获取class对象)

        *      2.interfaces:获取目标对象所有实现的接口(获取所有方法)

        *      3.invocationhandler:真正遍历处理每一个需要增强方法地方

        *         invoke方法: 访问一次interface的方法,该方法就调用一次

        * */

       YuLeQuan proxy = (YuLeQuan) Proxy.newProxyInstance(

              yl.getClass().getClassLoader(),

              yl.getClass().getInterfaces(),

              new InvocationHandler() {

                  //proxy:代理

                  //method:封装了每一个遍历的方法

                  //args:方法参数

                  //object  返回值

                  @Override

                  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                     System.out.println("开始");

                     //调用方法并返回

                     Object obj = method.invoke(yl, args);

                      System.out.println("结束");

                     return obj;

                  }

              });

      

       //3.调用代理对象方法

       proxy.play();

       proxy.kongfu();

 

  • Cglib的动态代理(目标类)
  • 导入jar(cglib.jar,asm.jar)
//1.创建目标类对象

        Lyf lyf = new Lyf();

       

        //2.创建代理对象

        Enhancer enhancer = new Enhancer();

          //2.1 说明父子关系

          enhancer.setSuperclass(Lyf.class);

          //2.2 方法怎么处理(回调机制)  拦截每一个方法然后添加增强

          enhancer.setCallback(new MethodInterceptor() {

            @Override

            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

                System.out.println("开始");

                Object obj = method.invoke(lyf, args);

                System.out.println("结束");

                return obj;

            }

        });

        Lyf ly = (Lyf) enhancer.create();

       

        //3.调用方法

        ly.play();

猜你喜欢

转载自blog.csdn.net/qq_42246689/article/details/83446290
今日推荐