码迷,mamicode.com
首页 > 编程语言 > 详细

java 反射浅析

时间:2015-07-24 18:16:06      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:java   反射   

最近看rpc框架,中间用到了反射,以前也早就听说过反射,用处大大的广。

反射的作用

Java的反射机制、能够在java运行时根据类的路径去获取与路径对应的Class对象。在根据这个类对象去获取类的成员变量、方法、构造这些东西、哪怕他们是私有的。获取到这些东西来做什么?你可以用他们来判断、也可以调用他们去完成某些功能。
反射机制就是专门帮我们做那些重复的有规则的事情。

反射的常用用法:

  • 利用打开office软件的demo,不用修改main程序,根据输入动态地调用对应的office,方便扩展。
package office;

public class Office {
    public static void main(String[] args) {
        Class c = null;
        try {
            c = Class.forName(args[0]);
        } catch (ClassNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        OfficeAble office = null;

        try {
            office =  (OfficeAble) c.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        office.start();
    }

}
package office;

public interface OfficeAble {
    public void start();
}
package office;

public class Excel implements OfficeAble{

    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("Excel...start...");
    }

}
package office;

public class Word implements OfficeAble{

    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("Word...start...");

    }


}
  • 下面是反射的常用用法展示:包括获取类类型的几种方法、利用类类型生成对象、获取方法名字、变量、构造函数、函数返回值、函数调用、以及一个表现反射是发生在运行期的。
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

//打印类中的相关信息,包括方法名、成员变量、构造函数
public class ReflectTest3 {

    //获取类类型的几种方法
    public void getClassType() {

        // one
        Class c1 = A.class;
        System.out.println(c1);
        //second
        A a = new A();
        Class c2 = a.getClass();
        System.out.println(c2);
        System.out.println(c1 == c2);
        //third
        Class c3 = null;
        try {
            c3 = Class.forName("A");
            System.out.println(c3);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        //利用类类型去生成对象
        try {
            A test = (A) c1.newInstance();
            test.print();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    //打印方法信息
    public void printMethodMessage(Object object) {
        //获取类类型
        Class test = object.getClass();
        //获取方法名数组,获取返回值、方法名、参数类型
        Method[] methods = test.getMethods();
        for(int i=0; i<methods.length; ++i) {
            Class returnType = methods[i].getReturnType();
            System.out.print(returnType.getName()+ "");  //返回值
            System.out.print(methods[i].getName()+ "(");   //方法名
            Class[] paramTypes = methods[i].getParameterTypes();
            for(Class class1:paramTypes) {
                System.out.print(class1.getName());
            }
            System.out.println(")");
        }

    }

    //获取类的public的成员变量
    public void printFieldMessage(Object object) {
        Class c = object.getClass();
        Field[] fields = c.getDeclaredFields();
        for(Field field: fields) {
            Class fieldType = field.getType();
            String typeName = fieldType.getName();  //获取类型名
            String fieldName = field.getName();  //获取变量名
            System.out.println(typeName + " " + fieldName);         
        }
    }


    //获取构造函数的信息
    public  void printConMessage(Object object) {
        Class c = object.getClass();
        //构造函数也是对象
        Constructor[] constructors = c.getDeclaredConstructors();
        for(Constructor cs: constructors) {
            System.out.print(cs.getName()+"(");  //获取构造函数名字
            Class[] paramTypes = cs.getParameterTypes();
            for(Class paramType:paramTypes) {
                System.out.print(paramType.getName()+ " ");
            }
            System.out.println(")");
        }
    }


    //方法反射
    public  void methodReflect() {
        //获取类类型
        A a = new A();
        Class c = a.getClass();

        //获取方法对象
        try {
            Method m1 = c.getMethod("print");
            m1.invoke(a);

            Method m2 = c.getMethod("print", int.class, int.class);
            m2.invoke(a, 1, 2);

            Method m3 = c.getMethod("print", String.class, String.class);
            m3.invoke(a, "hello", "world");


        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }

    //反射是在运行期的,绕过了编译器
    //通过arraylist添加不同类型的数据,来看看这个特性
    public void runtimeTest() {
        ArrayList<String> test = new ArrayList<String>();
        test.add("hello");
        //test.add(20);    //编译器报错
        Class c = test.getClass();
        Method m;
        try {
            m = c.getMethod("add", Object.class);
            m.invoke(test, 20);
            System.out.println(test.size());   //通过反射,已经将20添加到了ArrayList<String>中,绕过了编译器的语法检查
            System.out.println(test);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }       
    }
    //test method
    public static void main(String[] args) {
        ReflectTest3 test  = new ReflectTest3(); 
        System.out.println("-------------------分割线--获取类类型的几种方法-------------------");
        test.getClassType();

        System.out.println("-------------------分割线--打印方法信息-------------------");
        String s = "hello";
        test.printMethodMessage(s);   

        System.out.println("-------------------分割线--打印变量名信息-----------------");
        test.printFieldMessage(s);  

        System.out.println("-------------------分割线--打印构造函数信息--------------");
        test.printConMessage(s);   


        System.out.println("-------------------分割线--使用方法反射-----------------");       
        test.methodReflect();

        System.out.println("-------------------分割线--反射是在运行期的-----------------");         
        test.runtimeTest();
    }


}


class A {
    public void print() {
        System.out.println("hello,world");
    }

    public void print(int a, int b) {
        System.out.println(a+b);
    }

    public void print(String a, String b) {
        System.out.println(a.toUpperCase()+","+b.toLowerCase());
    }
}

运行结果:

-------------------分割线--获取类类型的几种方法-------------------
class A
class A
true
class A
hello,world
-------------------分割线--打印方法信息-------------------
booleanequals(java.lang.Object)
java.lang.StringtoString()
inthashCode()
intcompareTo(java.lang.Object)
intcompareTo(java.lang.String)
intindexOf(java.lang.Stringint)
intindexOf(int)
intindexOf(intint)
intindexOf(java.lang.String)
java.lang.StringvalueOf(float)
java.lang.StringvalueOf(double)
java.lang.StringvalueOf(boolean)
java.lang.StringvalueOf([Cintint)
java.lang.StringvalueOf([C)
java.lang.StringvalueOf(java.lang.Object)
java.lang.StringvalueOf(char)
java.lang.StringvalueOf(int)
java.lang.StringvalueOf(long)
charcharAt(int)
intcodePointAt(int)
intcodePointBefore(int)
intcodePointCount(intint)
intcompareToIgnoreCase(java.lang.String)
java.lang.Stringconcat(java.lang.String)
booleancontains(java.lang.CharSequence)
booleancontentEquals(java.lang.StringBuffer)
booleancontentEquals(java.lang.CharSequence)
java.lang.StringcopyValueOf([Cintint)
java.lang.StringcopyValueOf([C)
booleanendsWith(java.lang.String)
booleanequalsIgnoreCase(java.lang.String)
java.lang.Stringformat(java.util.Localejava.lang.String[Ljava.lang.Object;)
java.lang.Stringformat(java.lang.String[Ljava.lang.Object;)
[BgetBytes()
[BgetBytes(java.lang.String)
voidgetBytes(intint[Bint)
[BgetBytes(java.nio.charset.Charset)
voidgetChars(intint[Cint)
java.lang.Stringintern()
booleanisEmpty()
intlastIndexOf(int)
intlastIndexOf(intint)
intlastIndexOf(java.lang.Stringint)
intlastIndexOf(java.lang.String)
intlength()
booleanmatches(java.lang.String)
intoffsetByCodePoints(intint)
booleanregionMatches(intjava.lang.Stringintint)
booleanregionMatches(booleanintjava.lang.Stringintint)
java.lang.Stringreplace(charchar)
java.lang.Stringreplace(java.lang.CharSequencejava.lang.CharSequence)
java.lang.StringreplaceAll(java.lang.Stringjava.lang.String)
java.lang.StringreplaceFirst(java.lang.Stringjava.lang.String)
[Ljava.lang.String;split(java.lang.String)
[Ljava.lang.String;split(java.lang.Stringint)
booleanstartsWith(java.lang.String)
booleanstartsWith(java.lang.Stringint)
java.lang.CharSequencesubSequence(intint)
java.lang.Stringsubstring(intint)
java.lang.Stringsubstring(int)
[CtoCharArray()
java.lang.StringtoLowerCase()
java.lang.StringtoLowerCase(java.util.Locale)
java.lang.StringtoUpperCase(java.util.Locale)
java.lang.StringtoUpperCase()
java.lang.Stringtrim()
voidwait(longint)
voidwait(long)
voidwait()
java.lang.ClassgetClass()
voidnotify()
voidnotifyAll()
-------------------分割线--打印变量名信息-----------------
[C value
int hash
long serialVersionUID
[Ljava.io.ObjectStreamField; serialPersistentFields
java.util.Comparator CASE_INSENSITIVE_ORDER
int HASHING_SEED
int hash32
-------------------分割线--打印构造函数信息--------------
java.lang.String([B )
java.lang.String([B int int )
java.lang.String([B java.nio.charset.Charset )
java.lang.String([B java.lang.String )
java.lang.String([B int int java.nio.charset.Charset )
java.lang.String(int int [C )
java.lang.String([C boolean )
java.lang.String(java.lang.StringBuilder )
java.lang.String(java.lang.StringBuffer )
java.lang.String([I int int )
java.lang.String([C int int )
java.lang.String([C )
java.lang.String(java.lang.String )
java.lang.String()
java.lang.String([B int int java.lang.String )
java.lang.String([B int )
java.lang.String([B int int int )
-------------------分割线--使用方法反射-----------------
hello,world
3
HELLO,world
-------------------分割线--反射是在运行期的-----------------
2
[hello, 20]

反射的应用

工厂方法、代理+代理=动态代理(应用在spring的AOP上)、ibatis等
下面是我用maven+java反射+注解+jdbc写的一个简单的orm,代码放在github:https://github.com/zy416548283/JDBCSimpleORM

反射优缺点

优点:按名称动态检索信息,让运行中的程序操作这些信息,无需提前硬编码目标类。
缺点:性能问题.

反射原理

待分析

版权声明:本文为博主原创文章,未经博主允许不得转载。

java 反射浅析

标签:java   反射   

原文地址:http://blog.csdn.net/zy416548283/article/details/47044749

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!