java 反射详解
2015-12-22 23:04
337 查看
原本是做Android开发的,最近才转到web上来,接触了springMVC,大家都知道spring框架大量使用了Java反射的技术,所以在深入之前先来熟悉下Java的反射,记录下来
Java反射
说到Java的反射不得不提Class类,Java是面向对象的语言,任何事物都可以封装成一个类,所以类这个抽象的概念也是一个类,那就是Java中的Class类。至于Class的api大家可以看jdk源码。反射的基本原理就是通过给定的完整类名,可以得到类的实例对象,方法,构造方法,属性等等类的所有信息。看下面的例子:
得到类的实例对象:
调用类中的方法:
getMethod方法的第一个参数是方法名,第二个参数是方法参数的类型,如果没有参数可以传null。invoke方法的第一个参数是类实例,至于类实例的获取后面会讲到,第二个参数是要传递的参数,如果没有参数,和上面一样可以传null,invoke的返回值类型是object类型最后需要强转,方法的返回值类型可以通过method.getReturnType()获取。这样就达到了利用发射调用类中方法的目的。
得到构造方法
通过newInstance()获取类实例,类中需要有默认的无参构造方法,如果类中定义了有参构造方法,而类中又没有无参构造方法,怎么办呢,看下面的例子:
getConstructor是根据构造方法的参数获取指定的构造方法,其中getConstructor的参数就是构造方法的参数类型;getConstructors是获取了类中的所有构造方法,这样就可以调用Constructor的newInstance方法获取类的实例,newInstance方法的参数就是构造方法的参数,如果构造方法没有参数就传null,当然完全可以使用Class的newInstance方法直接获取类的实例对象。
Java的反射还有很多知识,比如获取类的属性、接口等等,大家有时间可以看看。
在spring框架中需要配置beans.xml文件,spring容器就是解析xml文件,然后根据class属性值利用Java的反射特性实例化类对象,然后以beans.xml中配置的id为key值,实例化的对象为value保存到map中的。spring的核心功能依赖注入(IOC)或者或者控制反转(DI)充分利用了这种方式使得程序中对象的依赖者和被依赖者之间的关系最大程度的实现了分离,使得程序的耦合性降到最低。比较好的理解例子见此:http://outofmemory.cn/java/spring/spring-ioc-meaning。
Java反射
说到Java的反射不得不提Class类,Java是面向对象的语言,任何事物都可以封装成一个类,所以类这个抽象的概念也是一个类,那就是Java中的Class类。至于Class的api大家可以看jdk源码。反射的基本原理就是通过给定的完整类名,可以得到类的实例对象,方法,构造方法,属性等等类的所有信息。看下面的例子:
得到类的实例对象:
public class Foo { private String str; private int Int; public Foo() { super(); } public Foo(String str, int i) { super(); this.str = str; Int = i; } public String getStr() { return str; } public void setStr(String str) { this.str = str; } public int getInt() { return Int; } public void setInt(int i) { Int = i; } private String foo() { System.out.println("private 无参 有返回值"); return "private 无参 有返回值"; } public void bar(String str) { System.out.println("public 无参 无返回值: 反射传过来的值:" + str); } @Override public String toString() { return "[str=" + str + ";Int=" + Int + "]"; } }要得到类的实例首先得到Class,最常用的一种方法是Class.forName,比如:
public class Test { public static void main(String[] args) { Class<?> c1 = null; try { c1 = Class.forName("com.test.Foo"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } } }forName中的参数就是类的完整类名。
调用类中的方法:
public class Test { /** * @param args */ public static void main(String[] args) { Class<?> c1 = null; try { c1 = Class.forName("com.test.Foo"); Method method = c1.getMethod("bar", String.class); method.invoke(c1.newInstance(), "反射调用方法"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } } }
getMethod方法的第一个参数是方法名,第二个参数是方法参数的类型,如果没有参数可以传null。invoke方法的第一个参数是类实例,至于类实例的获取后面会讲到,第二个参数是要传递的参数,如果没有参数,和上面一样可以传null,invoke的返回值类型是object类型最后需要强转,方法的返回值类型可以通过method.getReturnType()获取。这样就达到了利用发射调用类中方法的目的。
得到构造方法
通过newInstance()获取类实例,类中需要有默认的无参构造方法,如果类中定义了有参构造方法,而类中又没有无参构造方法,怎么办呢,看下面的例子:
public class Test { /** * @param args */ public static void main(String[] args) { Class<?> c1 = null; try { c1 = Class.forName("com.test.Foo"); Method method = c1.getMethod("bar", String.class); method.invoke(c1.newInstance(), "反射调用方法"); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } System.out.println(c1.getName()); try { Constructor<?> con =c1.getConstructor(String.class, int.class); Foo foo = (Foo) con.newInstance("String", 100); System.out.println(foo.toString()); Constructor<?>[] con1 =c1.getConstructors(); Foo foo1 = (Foo) con1[1].newInstance("String", 101); System.out.println(foo1.toString()); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } }
getConstructor是根据构造方法的参数获取指定的构造方法,其中getConstructor的参数就是构造方法的参数类型;getConstructors是获取了类中的所有构造方法,这样就可以调用Constructor的newInstance方法获取类的实例,newInstance方法的参数就是构造方法的参数,如果构造方法没有参数就传null,当然完全可以使用Class的newInstance方法直接获取类的实例对象。
Java的反射还有很多知识,比如获取类的属性、接口等等,大家有时间可以看看。
在spring框架中需要配置beans.xml文件,spring容器就是解析xml文件,然后根据class属性值利用Java的反射特性实例化类对象,然后以beans.xml中配置的id为key值,实例化的对象为value保存到map中的。spring的核心功能依赖注入(IOC)或者或者控制反转(DI)充分利用了这种方式使得程序中对象的依赖者和被依赖者之间的关系最大程度的实现了分离,使得程序的耦合性降到最低。比较好的理解例子见此:http://outofmemory.cn/java/spring/spring-ioc-meaning。
相关文章推荐
- Java中的简单工厂模式
- Java 之Date类
- Java---实力弹弹球,弹弹弹
- Java---实力弹弹球,弹弹弹
- Struts2环境的搭建
- Java线程:堵塞队列与堵塞栈
- spring component-scan filter
- Java中的类型转换和进制转换
- java异常处理机制Exception
- java异常
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序
- Java HashMap排序