java 反射浅析

来源:互联网 发布:java启动exe程序 编辑:程序博客网 时间:2024/06/06 06:59

最近看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 Aclass Atrueclass Ahello,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 valueint hashlong serialVersionUID[Ljava.io.ObjectStreamField; serialPersistentFieldsjava.util.Comparator CASE_INSENSITIVE_ORDERint HASHING_SEEDint 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,world3HELLO,world-------------------分割线--反射是在运行期的-----------------2[hello, 20]

反射的应用

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

反射优缺点

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

反射原理

待分析

0 0
原创粉丝点击