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为参数值
} 

 

  

 

 

posted @ 2013-08-12 21:01  石沉溪涧  阅读(376)  评论(0编辑  收藏  举报