zoukankan      html  css  js  c++  java
  • Java 反射机制总结

    关于反射:

    part1:备用知识:一般认同的定义是:程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言。Perl,Python,Ruby是动态语言,而java和c++、c#是静态语言。但是不同于c++,java有一个非常突出的动态机制,就是反射。

    part2:两个术语:

      Reflection反射。 我们可以于运行时加载、探知、使用编译期间完全未知的classes。即Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods     定义),并生成其对象实体、或对其fields设值、或唤起其methods。

      introspection反省,内省。the ability of the program to examine itself。是一种看透自己的能力。

    part3:一般流程:获得类型类->通过类型类获取当前运行的类的相关信息(获得相应方法、字段、或者实例)

    1.获得某个类的类型类:

     class<?> type=对象.getClass()=类.class=Class.ForName("包.类");

    tips:所有类的对象其实都是Class的实例

    2.通过类型类获取该类型的相关信息:

    类型类.getName() 获得此类运行时的类名

    类型类.getSuperclass() 获得此类运行时的父类

    类型类.getInterfaces()获得此类运行时的所拥有的接口

    3.通过类型类实例化其他类(其他类是指非自己,非类型类)
     
      a.通过无参数的构造函数
     
    Class<?> demo=Class.forName( "Reflect.Person" );
    Person per=(Person)demo.newInstance();
    

     注意要用无参数的构造函数必须保证有无参数的构造函数。比如:你写了一个有参数的构造函数,默认构造函数就被覆盖了,所以要再自己写一个无参构造函数。

       否则报错:

          

       b.通过有参数的构造函数,需要提取他的构造函数


    public Object newInstance(String className, Object[] args) throws Exception {  
         Class newoneClass = Class.forName(className);  
         Class[] argsClass = new Class[args.length];  
         for (int i = 0, j = args.length; i < j; i++) {  
             argsClass[i] = args[i].getClass();  
         }  
         Constructor cons = newoneClass.getConstructor(argsClass);  
         return cons.newInstance(args);  
    }
    

    part3:用途:spring ,struts,hibernate中都有用到,通过配置文件改进Class.ForName("path")中每次都要改动类的所在路径(包名+类名),而改变代码的麻烦。实现不用修改源码来改变代码的功能。

    没用反射前(工厂模式):

    interface fruit{
        public abstract void eat();
    }
     
    class Apple implements fruit{
        public void eat(){
            System.out.println("Apple");
        }
    }
     
    class Orange implements fruit{
        public void eat(){
            System.out.println("Orange");
        }
    }
     
    // 构造工厂类
    class Factory{
        public static fruit getInstance(String fruitName){
            fruit f=null;
            if("Apple".equals(fruitName)){
                f=new Apple();
            }
            if("Orange".equals(fruitName)){
                f=new Orange();
            }
            return f;
        }
    }
    class hello{
        public static void main(String[] a){
            fruit f=Factory.getInstance("Orange");
            f.eat();
        }
     
    }
    

    用了反射后:

    package Reflect;
     
    interface fruit{
        public abstract void eat();
    }
     
    class Apple implements fruit{
        public void eat(){
            System.out.println("Apple");
        }
    }
     
    class Orange implements fruit{
        public void eat(){
            System.out.println("Orange");
        }
    }
     
    class Factory{
        public static fruit getInstance(String ClassName){
            fruit f=null;
            try{
                f=(fruit)Class.forName(ClassName).newInstance();//ClassName在配置文件中取出来
            }catch (Exception e) {
                e.printStackTrace();
            }
            return f;
        }
    }
    class hello{
        public static void main(String[] a){
            fruit f=Factory.getInstance("Reflect.Apple");
            if(f!=null){
                f.eat();
            }
        }
    }
    

      

    plus:

    1.Class 、Field 、Constructor 等类中的getModifiers() 方法: 以整数形式返回此 Constructor 对象所表示构造方法的 Java 语言修饰符.public为3,private、protected都有对应的值 。可以用Modifier.isPublic(Classname.getModifiers())来判断修饰符是否是哪个。

    2.invoke方法:通过函数名反射相应的函数

    public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {  
     //返回值Object是指meshodName的返回值
         Class ownerClass = owner.getClass();  
         Class[] argsClass = new Class[args.length];  
        for (int i = 0, j = args.length; i < j; i++) {  
             argsClass[i] = args[i].getClass();  
         }  
         Method method = ownerClass.getMethod(methodName,argsClass);  //argsClass是所对应参数类型的类类型
         return method.invoke(owner, args);  //若owner换成null,则表示取出静态方法。args为参数值
    } 
    

      

  • 相关阅读:
    《Python 源码阅读》之 类型Type
    《Python 源码剖析》之对象
    KMP匹配算法
    Python的递归深度
    js验证手机号
    Jquery 实现 “下次自动登录” 记住用户名密码功能
    js注册读秒进度条
    div+css进度条
    SprignMVC+myBatis整合
    ssm控制输出sql(二)
  • 原文地址:https://www.cnblogs.com/Mrs-cc/p/3253967.html
Copyright © 2011-2022 走看看