zoukankan      html  css  js  c++  java
  • Java入门(12)Java反射

    序言

    Why--指的是为什么做这件事,也既事物的本质。

     反射之中包含了一个“反”的概念,所以要想解释反射就必须先从“正”开始解释,一般而言,当用户使用一个类的时候,应该先知道这个类,而后通过这个类产生实例化对象,但是“反”指的是通过对象找到类。

    package cn.mf.demo4;
    
    public class Person {
        public String name;
        private int age;
    
        public Person() {
        }
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public void eat() {
            System.out.println("人吃饭");
        }
    
        public void sleep() {
            System.out.println("人在睡觉");
        }
    
        public void playGame() {
            System.out.println("人在打游戏");
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
    }
    Person
        @Test
        public void function1()  {
            Person p = new Person() ; //正着操作
            Class<?> c = p.getClass();//反着来
            System.out.println(c.getName()); 
        }

    对于对象的实例化操作,除了使用关键字new之外又多了一个反射机制操作,而且这个操作要比之前使用的new复杂一些,可是有什么用?

    对于程序的开发模式之前一直强调:尽量减少耦合,而减少耦合的最好做法是使用接口,但是就算使用了接口也逃不出关键字new,所以实际上new是造成耦合的关键元凶。

    我们以传统的工厂模式为例,看看存在的问题

    IBaoCaiMing 报菜名接口

    package cn.mf.demo;
    
    public interface IBaoCaiMing {
         public void BaoCaiMing();
    }

    ZhengXiongZhang 蒸熊掌实现报菜名

    package cn.mf.demo;
    
    public class ZhengXiongZhang implements IBaoCaiMing{
    
        @Override
        public void BaoCaiMing() {
            System.out.println("蒸熊掌"); 
        }
    
    }

    ZhengYaoGao蒸羊羔实现报菜名

    package cn.mf.demo;
    
    public class ZhengYaoGao implements IBaoCaiMing {
    
        @Override
        public void BaoCaiMing() {
            System.out.println("蒸羊羔"); 
        }
    
    }

    然后,我们实现一个静态的工厂方法,在这个工厂类中,静态地得到报菜名的实例

    public class Factory {
        public static IBaoCaiMing ZhengXiongZhang() {
            return new ZhengXiongZhang();
        }
    
        public static IBaoCaiMing ZhengYaoGao() {
            return new ZhengYaoGao();
        }
    }

    此时,如果我们把蒸鹿尾儿、烧花鸭、烧雏鸡、烧子鹅。。。。。。一百多道菜都添加进去,我们就需要修改一百多次工厂类。麻烦的一笔!

    但是如果使用反射机制修改工厂模式就可以很好的解决以上问题,代码修改如下:

    public class Factory {
        public static IBaoCaiMing getInstance(String className) {
            IBaoCaiMing bcm = null;
            try {
                bcm = (IBaoCaiMing) Class.forName(className).newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bcm;
        }
    }

    调用(有木有发现随便增加菜名,Factory压根就不用做任何修改,可谓以不变应万变)

        @Test
        public void BaoCaiMingTest()  {
            IBaoCaiMing bcm1 = Factory.getInstance("cn.mf.demo.ZhengXiongZhang") ;
            bcm1.BaoCaiMing() ;
            IBaoCaiMing bcm2 = Factory.getInstance("cn.mf.demo.ZhengYaoGao") ;
            bcm2.BaoCaiMing() ;
        }

    How--指的是怎样去做一件事,也就是做事的方法、方式。

    Java的反射机制的实现要借助于4个类:classConstructorFieldMethod;

    其中class代表的时类对 象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组 成部分。

    1、得到构造器的方法

    Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数, 
     
    Constructor[] getConstructors() -- 获得类的所有公共构造函数 
     
    Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关) 
     
    Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

    2、获得字段信息的方法

    Field getField(String name) -- 获得命名的公共字段 
     
    Field[] getFields() -- 获得类的所有公共字段 
     
    Field getDeclaredField(String name) -- 获得类声明的命名的字段 
     
    Field[] getDeclaredFields() -- 获得类声明的所有字段

    3、获得方法信息的方法

    Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法 
     
    Method[] getMethods() -- 获得类的所有公共方法 
     
    Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法 
     
    Method[] getDeclaredMethods() -- 获得类声明的所有方法

    反射的应用场景

    反射常见的应用场景:

    1. Spring 实例化对象:当程序启动时,Spring 会读取配置文件applicationContext.xml并解析出里面所有的 标签实例化到IOC容器中。
    2. 反射 + 工厂模式:通过反射消除工厂中的多个分支,如果需要生产新的类,无需关注工厂类,工厂类可以应对各种新增的类,反射可以使得程序更加健壮。
    3. JDBC连接数据库:使用JDBC连接数据库时,指定连接数据库的驱动类时用到反射加载驱动类
    4. orm

    继续思考中。。。回头继续完善。。。

    资料

     

  • 相关阅读:
    Ant
    责任链模式
    日志logback
    知识点
    三个实例演示 Java Thread Dump 日志分析
    IDEA运行编译后配置文件无法找到,或配置文件修改后无效的问题
    IDEA创建MAVEN WEB工程
    多线程源码分析ThreadPoolExecutor
    解决
    微博关系服务与Redis的故事
  • 原文地址:https://www.cnblogs.com/cnki/p/8722157.html
Copyright © 2011-2022 走看看