天天看点

Java反射机制研究

http://blog.csdn.net/jia635/article/details/39256187

以前听同时说反射很强大,看了一些相关文章今天把反射总结一下。

说明:反射主要用于开发框架,即制作框架;

一、获得class对象

class<?> c = class.forname("classname");   抛出classnotfoundexception

二、获得实现接口

class<?> inters[] = c.getinterfaces();

for(int i=0;i<inters.length;i++){

    system.out.print(inters[i].getname()+" ");        //getname()方法为取得接口名称;

}

三、获得父类

class<?> superclass  = c.getsuperclass();     //获得父类

string name  = superclass.getname();    //获得父类名称

四、取得构造方法

constructor cons[] = c.getconstructors();         //获得公开的构造方法

constructor dcons[] = c.getdeclaredconstructors();        //获得全部构造方法

string modifier = modifier.tostring(cons[i].getmodifiers());   //获得访问权限

string name = cons[i].getname();            //获得构造方法名称

class<?> params[] = cons[i].getparametertypes();        //获得参数类型对象

五、获得method

method ms[] = c.getmethods();                        //返回公共的全部方法,包括继承方法

method dms[] = c.getdeclaredmethods();        //返回本类全部方法,不包括继承的方法

class<?> rt = ms[i].getreturntype();

class<?>params[] = ms[i].getparametertypes();

string name = ms[i].getname();

string modifier = modifier.tostring(ms[i].getmodifiers());

class<?>ex[] = ms[i].getexceptiontypes();        //获得异常

string name = ex[i].getname();            //获得异常名称

六、获得field

field fs[] = c.getfields();                    //获得公共属性,包括继承属性

field dfs[] = c.getdeclaredfields();    // 获得本类全部属性

class<?> type = fs[i].gettype();        //获得属性的类型对象

string name = fs[i].getname();        //获得属性的名称

string modifier = modifier.tostring(fs[i].getmodifiers());

七、通过反射创建一个对象

(1)

class<?> c = class.forname("person");

person p = (person)c.newinstance();

(2)

constructor con = c1.getconstructor(class....param);

object obj = con.newinstance(object obj);  //根据构造函数创建一个实例

八、constructor创建对象

class c = class.forname("person");

constructor<?> cons[] = c.getconstructors();

person p = (person)cons[0].newinstance("xiazdong",15);

注:如果调用的构造函数为私有,则需要c.setaccessible(true);

九、调用特定方法

method m = c1.getmethod("funcname",class<?>...c);   //funcname表示调用方法的名称,c表示参数的class对象

例如:method m = c1.getmethod("fun",string.class,int.class);    表示调用fun(string,int);函数

object obj = m.invoke(c1.newinstance(),"xiazdong",20);   //如果有返回值,则invoke函数返回;

注:如果是调用静态的方法,则不需要设置对象;

object obj = m.invoke(null,"xiazdong");

注:如果参数中有数组,比如 public static void main(string[]args);

method m = c1.getmethod("main",string[].class);

m.invoke(null,(object)new string[]{"aa","bb"});是对的;

m.invoke(null,new string[]{"aa","bb"}); 会调用 main(string,string);函数;

十、调用特定属性

field f = c1.getdeclaredfield("name");    //返回name属性

f.setaccessible(true);    //私有属性可见

string name = (string)f.get(object obj);   //返回obj对象的name属性的值

f.set(object obj,string n);      //设置obj对象的name属性为n值;

十一、操作数组

int tmp[] = {1,2,3};

class<?> c  = tmp.getclass().getcomponenttype();

array.getlength(tmp);        //tmp数组的长度

c.getname();           //获得数组类型名称

array.get(object obj,int index);      //获得obj数组的index索引的数值

array.set(object obj,int index,value);    //设置obj数组的index索引的数值为value;

object obj  = array.newinstance(c,length);          //c为数组的类型,length为数组的长度;obj为返回的数组对象;

示例:

[java]

view plaincopyprint?

import java.lang.reflect.*;  

public class getmethoddemo01{  

    public static void main(string args[])throws exception{  

        class<?> c1 = class.forname("person");  

        method m = c1.getmethod("sayhello");  

        m.invoke(c1.newinstance());  

        method m2 = c1.getmethod("sayhello2",string.class,int.class);  

        string str = (string)m2.invoke(c1.newinstance(),"xiazdong",123);  

        system.out.println(str);  

        field namefield = c1.getdeclaredfield("name");  

        field agefield = c1.getdeclaredfield("age");  

        namefield.setaccessible(true);  

        agefield.setaccessible(true);  

        person obj = (person)c1.newinstance();  

        obj.setname("xzdong");  

        obj.setage(12);  

        system.out.println(namefield.get(obj));  

        system.out.println(agefield.get(obj));  

        method setname = c1.getmethod("setname",string.class);  

        setname.invoke(obj,"changed");  

        method getname = c1.getmethod("getname");  

        system.out.println(getname.invoke(obj));  

        int tmp[] = {1,2,3};  

        class<?> c3 = tmp.getclass().getcomponenttype();  

        system.out.println(c3.getname());  

        system.out.println("第一个数:"+array.get(tmp,0));  

        array.set(tmp,0,5);  

        object arr = array.newinstance(c3,5);  

        system.arraycopy(tmp,0,arr,0,array.getlength(tmp));  

        system.out.println(array.get(arr,2));  

        system.out.println(array.get(arr,3));  

    }  

}  

interface china{  

    public static final string name = "china";  

    public int age = 60;  

    public void sayhello();  

    public string sayhello2(string name,int age);  

class person implements china{  

    private string name;  

    private int age;  

    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 void sayhello(){  

        system.out.println(name+"  "+age);  

    public string sayhello2(string name,int age){  

        return name+" "+age;  

十一、工厂设计模式

1.最简单的工厂设计模式

场景:有一个fruit接口,apple类和orange类都实现了fruit接口,factory用来生产水果;

import java.io.*;  

import java.util.*;  

interface fruit{  

    public void eat();  

class apple implements fruit{  

    public void eat(){  

        system.out.println("吃苹果");  

class orange implements fruit{  

        system.out.println("吃橘子");  

class factory{  

    public static fruit getinstance(string name)throws exception{  

        fruit f = null;  

        if("apple".equals(name)){  

            f = new apple();  

        }  

        else if("orange".equals(name)){  

            f = new orange();  

        if(f!=null){  

            return f;  

        else return null;  

public class factorydemo01{  

        fruit f = factory.getinstance("apple");  

        f.eat();  

2.通过反射实现

上面的例子有一个坏处,就是在factory的getinstance代码会随着水果数量增加而增加,比如如果增加了一个banana类,则需要添加

if(name.equals("banana")){...}

这样非常不方便,因此反射就是一个很好的解决方法:

        fruit f = null  

        fruit f = (fruit)class.forname(name).newinstance();  

3.增加灵活性:配置文件

但是还有一个缺点,就是如果apple类等有包名,则如果要访问此类,必须添加包名+类名称才可以。比如apple类的最上方:package org;则必须通过org.apple才可以访问apple类。因此通过properties文件可以解决这个问题;

        private factory(){}  

        properties p = new properties();  

        p.load(new fileinputstream("1.properties"));  

        string str = p.getproperty("apple");  

        fruit f = factory.getinstance(str);  

1.properties代码:

apple=apple

orange=orange