JAVA之反射

来源:互联网 发布:天猫淘宝网商城午蹈鞋 编辑:程序博客网 时间:2024/06/14 08:53

        Java反射是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时通过反射机制取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等)、superclass(例如Object)、实现于interfaces(例如Cloneable),也包括fields和methods的所有信息,并可在运行时改变fields内容或调用methods。

        Java反射机制允许程序在运行时加载、探知、使用编译期间完全未知的classes。换言之,Java可以加载一个运行时才得知名称的class,获得其完整结构。

一、相关API:

        在java.lang.reflect包中可以找到相关的API,常用的类和接口有:

        1、Member接口:获取类相关的成员信息,包括成员所在类的class对象,变量或方法的修饰符和名称等信息;

        2、AccessibleObject类:是域(field)对象、方法(method)对象、构造函数(constructor)对象的基类。它提供了将反射的对象标记为在使用时取消默认Java 语言访问控制检查的能力。

        3、Array类:提供动态创建和访问Java数组的方法。

        4、Constructor类:提供关于类的单个构造方法的信息以及对它的访问权限。

        5、Field类:提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)变量或实例变量。

        6、Method类:提供关于类或接口的单个方法,以及对它的动态访问权限。反射的方法可能是类方法或实例方法(包括抽象方法)。

        7、Modifier类:提供了对类、变量、方法的访问修饰符进行解码。

        8、Proxy类:提供创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

二、应用:

        1、获取类的class对象:

                ①可以调用对象的.getClass()方法,但原生类的变量不能调用此方法,比如int、boolean等:

public class Test{public static void main(String args[]){String str = new String();System.out.println(str.getClass());}}

                ②可以调用类的.class()方法,原生类也可以调用此方法,比如int、boolean等:

public class Test{public static void main(String args[]){System.out.println(String.class);}}
                ③可以调用Class类的静态方法.forName()

public class Test{public static void main(String args[]){try {System.out.println(Class.forName("java.lang.String"));} catch (ClassNotFoundException e) {e.printStackTrace();}}}

                ④原始包装类可以使用字段.Type

public class Test{public static void main(String args[]){System.out.println(Integer.TYPE);}}

        如果要获取布尔型的Class对象,可以使用如下方法,区别如下:

public class Test{public static void main(String args[]){//boolean b = true;//System.out.println(b.getClass());   原始类的变量不能调用.getClass()方法Class<?> c1=Boolean.TYPE;             //返回原始类型booleanSystem.out.println(c1); Class<?> c2=boolean.class;            //返回原始类型booleanSystem.out.println(c2);     Class<?> c3=Boolean.class;            //返回class java.lang.BooleanSystem.out.println(c3); }}

        2、创建对象:

                       ①使用Class对象的newInstance()方法,此方法只适用于无参数的构造方法:

public class Test{public static void main(String args[]){Class<?> clazz = String.class;try {Object str = clazz.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}

               ②使用Constructor对象的newInstance()方法:

                   1>如果是无参的构造方法:

import java.lang.reflect.*;public class Test{public static void main(String args[]){Class<?> clazz = String.class;try {Constructor<?> c = clazz.getConstructor();try {Object str = c.newInstance();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}
                   2>如果是有参的构造方法:
import java.lang.reflect.*;public class Test{public static void main(String args[]){Class<?> clazz = String.class;try {Constructor<?> c = clazz.getConstructor(String.class);try {Object str = c.newInstance("Hello World");} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IllegalArgumentException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}

        3、获取类的Fields(变量):

               ①public Field[] getFields():返回对应类/接口以及其所有父类/父接口的所有的公共变量;

               ②public Field getField(String name):返回对应类/接口以及其所有父类/父接口中指定名称的公共变量;

               ③public Field[] getDeclaredFields():返回对应类/接口中定义的所有的变量,但不包括继承来的变量;

               ④public Field getDeclaredField(String name):返回对应类/接口中定义过的指定名称的变量,但不包括继承来的变量;

假如有两个类有继承关系:

Test1:

public class Test1 {private String a;public String b;}

Test2:

public class Test2 extends Test1 {private String c;public String d;}
通过反射获取变量时:
import java.lang.reflect.Field;public class Test{public static void main(String args[]){Test2 t = new Test2();Class<?> clazz = t.getClass();Field[] fields1 = clazz.getFields();for(Field f:fields1){System.out.println(f.getName());    //取到b,d,无序}try {System.out.println(clazz.getField("b")); //public java.lang.String Test1.b(能取到b,d,但取不到a,c)} catch (NoSuchFieldException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}Field[] fields2 = clazz.getDeclaredFields();for(Field f:fields2){System.out.println(f.getName());     //取到c,d,无序}try {System.out.println(clazz.getDeclaredField("d")); //public java.lang.String Test2.d(能取到c,d,取不到a,b) } catch (NoSuchFieldException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}

        由此可见getFields和getDeclaredFields区别:

        ①getFields():返回对应类/接口以及其所有父类/父接口的所有的public变量;

        ②getDeclaredFields():返回类/接口中定义的所有变量,不包括父类中的。

        4、设置和获取类的Fields(变量)的值:获取Class对象的Field对象后调用Field类中类似set(Object o,Object value)方法。

import java.lang.reflect.*;public class Test{public int a;public String b;public int getA() {return a;}public void setA(int a) {this.a = a;}public String getB() {return b;}public void setB(String b) {this.b = b;}public static void main(String args[]){Class<?> clazz = Test.class;try {Object t = clazz.newInstance();try {Field f1 = clazz.getField("a");Field f2 = clazz.getField("b");try {f1.setInt(t, 100);f2.set(t, "Hello World");int a = f1.getInt(t);System.out.println(a);String b = f2.get(t).toString();System.out.println(b);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}} catch (NoSuchFieldException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}} catch (InstantiationException e1) {e1.printStackTrace();} catch (IllegalAccessException e1) {e1.printStackTrace();}}}
        5、获取类的Methods(方法):

               ①public Method[] getMethods():返回对应类/接口以及其所有父类/父接口的所有的公共方法;

               ②public Method getMethod(String name,Class<?>... parameterTypes):返回对应类/接口以及其所有父类/父接口中指定名称和参数类型的公共方法;

               ③public Method[] getDeclaredMethods():返回对应类/接口中定义的所有方法,但不包括继承来的方法;

               ④public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
:返回对应类/接口中定义过的指定名称的方法,但不包括继承来的方法;

假如有两个类有继承关系:

Test1:

public class Test1 {private void a(){}private void a(int m,int n){}public void b(){}public void b(int m,int n){}}

Test2:

public class Test2 extends Test1 {private void c(){}private void c(int m,int n){}public void d(){}private void d(int m,int n){}}

通过反射获取方法时:

import java.lang.reflect.Method;public class Test{public static void main(String args[]){Test2 t = new Test2();Class<?> clazz = t.getClass();Method[] Method1 = clazz.getMethods();for(Method m:Method1){System.out.println(m);    //取到b,d,无序}try {System.out.println(clazz.getMethod("b", int.class,int.class)); //public void Test1.b(int,int)(能取到b,d,但取不到a,c)} catch (NoSuchMethodException e1) {e1.printStackTrace();} catch (SecurityException e1) {e1.printStackTrace();}Method[] Method2 = clazz.getDeclaredMethods();for(Method m:Method2){System.out.println(m);    //取到c,d,无序}try {System.out.println(clazz.getDeclaredMethod("d")); //public void Test2.d() )(能取到c,d,但取不到a,b)} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}

        6、获取类的Constructors(构造方法):

               ①public Constructor<?>[] getConstructors():返回对应类的公共构造方法,但不包括父类的构造方法;

               ②public Constructor<T> getConstructor(Class<?>... parameterTypes):返回对应类但不包括其父类的指定相同参数类型的公共构造方法;

               ③public Constructor<?>[] getDeclaredConstructors():返回对应类中定义的所有的构造方法,但不包括继承来的构造方法;

               ④public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回对应类中定义的指定参数类型的构造方法,但不包括继承来的构造方法;

假如有两个类有继承关系:

Test1:

public class Test1 {public Test1(){}public Test1(int m){}public Test1(int m,int n){}private Test1(int m,int n,int x){}}

Test2:

public class Test2 extends Test1 {public Test2(){}public Test2(String str){}public Test2(String str1,String str2){}private Test2(String str1,String str2,String str3){}}

通过反射获取方法时:

import java.lang.reflect.Constructor;public class Test{public static void main(String args[]){Class<?> clazz = Test2.class;Constructor<?>[] constructors1 = clazz.getConstructors();for(Constructor<?> c:constructors1){System.out.println(c);}try {System.out.println(clazz.getConstructor(String.class,String.class));} catch (NoSuchMethodException e1) {e1.printStackTrace();} catch (SecurityException e1) {e1.printStackTrace();}Constructor<?>[] constructors2 = clazz.getDeclaredConstructors();for(Constructor<?> c:constructors2){System.out.println(c);}try {System.out.println(clazz.getDeclaredConstructor(String.class,String.class,String.class));} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}}}

        由此可见,获取构造方法与获取变量和方法的方法不同,它不能获取到其父类的构造方法。

        7、调用方法:获取Class对象的Method对象后调用Method类中invoke(Object o, Object... args)方法。

import java.lang.reflect.*;public class Test{public void testMethod(int a){System.out.println("testMethod:"+a);}public static void main(String args[]){Class<?> clazz = Test.class;try {Object t = clazz.newInstance();try {Method m = clazz.getMethod("testMethod", int.class);try {m.invoke(t, 3);} catch (InvocationTargetException e) {e.printStackTrace();}} catch (NoSuchMethodException e) {e.printStackTrace();} catch (SecurityException e) {e.printStackTrace();}} catch (InstantiationException e1) {e1.printStackTrace();} catch (IllegalAccessException e1) {e1.printStackTrace();}}}

        8、动态代理:动态代理即代理是在运行期发生的,而不是在编译上其发生的。

接口或抽象类:

public interface ProxyInterface {public void say(); }

实际作用类:

public class RealPart implements ProxyInterface{public void say() { System.out.println("RealPart"); }}

代理类:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class ProxyPart implements InvocationHandler {private Object obj; public ProxyPart(Object obj){ this.obj = obj; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {method.invoke(obj, args); return null; }}

主入口:

import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {RealPart real = new RealPart(); InvocationHandler handler = new ProxyPart(real); Class<?> clazz = handler.getClass(); ProxyInterface proxy = (ProxyInterface)Proxy.newProxyInstance(clazz.getClassLoader(),real.getClass().getInterfaces(),handler); System.out.println(proxy.getClass());  proxy.say(); }}

参考:http://www.cnblogs.com/Quincy/archive/2011/06/19/2084557.html#



0 0