java反射详解
2016-04-15 15:01
369 查看
本文主要针对java反射进行学习,以java.lang.reflect包中的接口和类进行学习和理解。文章目录如下:
java反射概念
java反射包接口详解
java发射包中类详解
java反射的应用例子
java反射能起到的作用:
- 在运行中分析类的能力,即动态获取类的基本情况;
- 通过反射机制访问java对象的属性,方法,构造方法等;
- 主要是为工具构造者提供的便利机制。
java.lang.reflect.AnnotatedElement接口是所有程序元素(例如java.lang.Class、java.lang.reflect.Method、java.lang.reflect.Constructor等)的父接口。该接口主要是功能是是获取指定元素上所有类型注解、判断指定元素上是否有指定的注解。下边举例:本文定义一个MyTag注解,然后使用AnnotatedElement接口提供的
定义公共实体类Person
自定义注解
测试端
运行结果:
2:InvocationHandler接口
InvocationHandler接口主要为用户创建动态代理,即每一个代理都需要实现该接口,它只有一个方法:
proxy:在其上调用方法的代理实例;
method:对应于在代理实例上调用的接口方法的 Method 实例;
args:包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null
下面创建一个动态代理,来说明该接口的使用过程:
创建日志处理接口及实现
测试端:
运行结果:
Array:主要用于动态的创建数字,当反射方法参数是数组时,可以使用Array来赋值。
Field:主要获取类中字段信息
Method:主要获取类中方法信息
Constructor:获取类中所有构造器函数信息
Modifier:获取类元素的权限访问标识
通过上述类中方法的调用,通过反射动态的获取类中所有信息,下面通过三个实例来说明java反射包中类的使用方法。
测试端实例:
运行结果:
测试端实例:
运行结果:
通过运行实例发现:通过这种方式不仅能够拷贝对象数组,而且可以扩展为任意类型数组。
测试端:
运行结果:
引用块内容
[1]java核心技术 卷I
java反射概念
java反射包接口详解
java发射包中类详解
java反射的应用例子
一:java反射概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。java反射能起到的作用:
- 在运行中分析类的能力,即动态获取类的基本情况;
- 通过反射机制访问java对象的属性,方法,构造方法等;
- 主要是为工具构造者提供的便利机制。
二:java反射包中的接口
1:AnnotatedElementjava.lang.reflect.AnnotatedElement接口是所有程序元素(例如java.lang.Class、java.lang.reflect.Method、java.lang.reflect.Constructor等)的父接口。该接口主要是功能是是获取指定元素上所有类型注解、判断指定元素上是否有指定的注解。下边举例:本文定义一个MyTag注解,然后使用AnnotatedElement接口提供的
isAnnotationPresent(Class<? extends Annotation> annotationClass)方法来判断指定方法上是否有该注解。
定义公共实体类Person
public class Person { private String name; private Integer age; private String address; public Person() { // TODO Auto-generated constructor stub setName("peter"); } public Person(String name,Integer age,String address) { this.address=address; this.age=age; this.name=name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @MyTag(name="peter") public void getInfo() { System.out.println("I am student!"); } @Override public String toString() { // TODO Auto-generated method stub return "Person:"+name+";"+address+";"+age; } }
自定义注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyTag { String name() default "test"; }
测试端
public class AnnotatedElementTest { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException { // TODO Auto-generated method stub Class<?> person=Class.forName("com.csu.reflect.Person"); boolean result=person.getMethod("getInfo", null).isAnnotationPresent( MyTag.class); System.out.println(result); } }
运行结果:
true
通过上述例子发现,该接口为java反射获取类元素注解信息提供方法,通过该接口可以方便的获取类、方法、变量等上边的注解类型、名称等。
2:InvocationHandler接口
InvocationHandler接口主要为用户创建动态代理,即每一个代理都需要实现该接口,它只有一个方法:
invoke(Object proxy, Method method, Object[] args)。
proxy:在其上调用方法的代理实例;
method:对应于在代理实例上调用的接口方法的 Method 实例;
args:包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null
下面创建一个动态代理,来说明该接口的使用过程:
创建日志处理接口及实现
public interface LogInfo { public void recordLog (); public void getLength(); }
public class RealLogInfo implements LogInfo{ @Override public void recordLog() { // TODO Auto-generated method stub System.out.println("记录系统运行的日志!"); } @Override public void getLength() { // TODO Auto-generated method stub System.out.println("获取日志长度!"); } }
import java.lang.reflect.Method; public class DynamicLogProxy implements InvocationHandler{ private Object infoObject; public DynamicLogProxy(Object object) { // TODO Auto-generated constructor stub this.infoObject=object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // TODO Auto-generated method stub //对象方法执行前调用一些方法,如spring的AOP System.out.println("Before happen something!"); method.invoke(infoObject, args); System.out.println("After happen something!"); return null; } }
测试端:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class InvocationHandlerDemo { public static void main(String[] args) { // TODO Auto-generated method stub //真实对象 LogInfo realInfo=new RealLogInfo(); InvocationHandler handler=new DynamicLogProxy(realInfo); //通过Proxy的newProxyInstance方法来创建我们的代理对象 LogInfo info=(LogInfo)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realInfo.getClass().getInterfaces(), handler); System.out.println(info.getClass().getName()); info.recordLog(); info.getLength(); } }
运行结果:
com.sun.proxy.$Proxy0 Before happen something! 记录系统运行的日志! After happen something! -------------------- Before happen something! 获取日志长度! After happen something!
从运行结果中发现:info实例获取的类名称竟然是$Proxy0,是的这就是代理的独特之处,在jvm中对代理类进行了统一的命名管理。同时我们发现,通过代理我们可以在方法运行前后进行一些特殊逻辑处理,Spring AOP正式使用这种思想。
三:java反射包中的类
AccessibleObject:设置反射过程元素是否通过java安全检查,默认未false,它是类Field, Method, Constructor, ReflectPermission父类;
Array:主要用于动态的创建数字,当反射方法参数是数组时,可以使用Array来赋值。
Field:主要获取类中字段信息
Method:主要获取类中方法信息
Constructor:获取类中所有构造器函数信息
Modifier:获取类元素的权限访问标识
通过上述类中方法的调用,通过反射动态的获取类中所有信息,下面通过三个实例来说明java反射包中类的使用方法。
实例一:获取某个类的所有信息
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; /** *通过反射方法获取类中详细信息 */ public class GetClassInfoByReflect { /** * 获取类中所有构造函数 */ @SuppressWarnings("rawtypes") public static void getAllConstructors(Class clazz) { Constructor[] constructors=clazz.getConstructors(); for(Constructor c:constructors) { String name=c.getName(); System.out.print(" "); String modifiers=Modifier.toString(clazz.getModifiers()); if(modifiers.length()>0) System.out.print(modifiers+" "); System.out.print(name+"("); Class []paramTypes=c.getParameterTypes(); for(int i=0;i<paramTypes.length;i++) { if(i>0) System.out.print(", "); System.out.print(paramTypes[i].getName()); } System.out.println(");"); } } /** * 获取类中所用方法 * @param clazz */ @SuppressWarnings("rawtypes") public static void getAllMethods(Class clazz) { Method[] methods=clazz.getMethods(); for(Method m:methods) { Class returntype=m.getReturnType(); String name=m.getName(); System.out.print(" "); String modifiers=Modifier.toString(m.getModifiers()); if(modifiers.length()>0) System.out.print(modifiers+" "); System.out.print(returntype.getName()+" "+name+"("); Class [] paramTypes=m.getParameterTypes(); for(int i=0;i<paramTypes.length;i++) { if(i>0) System.out.print(","); System.out.print(paramTypes[i].getName()); } System.out.println(");"); } } /** * 获取类中所有字段信息 * @param clazz */ @SuppressWarnings("rawtypes") public static void getAllFields(Class clazz) { Field [] fields=clazz.getDeclaredFields(); for(Field f:fields) { Class type=f.getType(); String name=f.getName(); System.out.print(" "); String modifier=Modifier.toString(f.getModifiers()); if(modifier.length()>0) System.out.print(modifier+" "); System.out.println(type.getName()+" "+name+";"); } } }
测试端实例:
public class ReflectTest { public static void main(String[] args) throws ClassNotFoundException { // TODO Auto-generated method stub Class clazz=Class.forName("com.csu.reflect.Person"); System.out.println("构造函数"); GetClassInfoByReflect.getAllConstructors(clazz); System.out.println("类函数"); GetClassInfoByReflect.getAllMethods(clazz); System.out.println("成员变量"); GetClassInfoByReflect.getAllFields(clazz); } }
运行结果:
构造函数 public com.csu.reflect.Person(); public com.csu.reflect.Person(java.lang.String, java.lang.Integer, java.lang.String); 类函数 public java.lang.String toString(); public java.lang.String getAddress(); public java.lang.String getName(); public void setName(java.lang.String); public java.lang.Integer getAge(); public void getInfo(); public void setAge(java.lang.Integer); public void setAddress(java.lang.String); public final void wait(long,int); public final native void wait(long); public final void wait(); public boolean equals(java.lang.Object); public native int hashCode(); public final native java.lang.Class getClass(); public final native void notify(); public final native void notifyAll(); 成员变量 private java.lang.String name; private java.lang.Integer age; private java.lang.String address;
实例二:使用反射类Array实现所有数组拷贝
public class GenericCopyArray { /** * 通用数组拷贝方法 * @param array * @param length * @return */ @SuppressWarnings("rawtypes") public static Object copyArray(Object array,int newlength) { Class clazz=array.getClass(); if(!clazz.isArray()) return null; Class type=clazz.getComponentType(); int length=Array.getLength(array); Object newArray=Array.newInstance(type, newlength); System.arraycopy(array, 0, newArray, 0, Math.min(length, newlength)); return newArray; } }
测试端实例:
import java.util.Arrays; public class Arraytest { public static void main(String[] args) { // TODO Auto-generated method stub /** * GenericCopyArray.copyArray不仅可以对象数组,还可以扩展任意类型的数组 */ int[] a={1,2,3}; a=(int[])GenericCopyArray.copyArray(a, 2); System.out.println(Arrays.toString(a)); Person person1=new Person("zp", 28, "changsha"); Person person2=new Person("wang", 29, "shandong"); Person person3=new Person("liu", 29, "wuhan"); Person [] persons={person1,person2}; Person []personCopy=(Person[])GenericCopyArray.copyArray(persons,2); System.out.println("拷贝结果:"+Arrays.toString(personCopy)); //改变拷贝数字的值 personCopy[0]=person3; System.out.println("改变拷贝结果"+Arrays.toString(personCopy)); System.out.println("原始结果未发生变化:"+Arrays.toString(persons)); } }
运行结果:
[1, 2] 拷贝结果:[Person:zp;address;28, Person:wang;address;29] 改变拷贝结果[Person:liu;address;29, Person:wang;address;29] 原始结果未发生变化:[Person:zp;address;28, Person:wang;address;29]
通过运行实例发现:通过这种方式不仅能够拷贝对象数组,而且可以扩展为任意类型数组。
实例三:通过Array给反射调用方法赋值
public class Target { public void printValue(String[] values) { for(String value:values) { System.out.println(value); } } }
测试端:
public static void main(String[] args) { // TODO Auto-generated method stub Class<Target> clazz =Target.class; try { Object object=clazz.newInstance(); Method printValue=clazz.getMethod("printValue", String[].class); Object array=Array.newInstance(String.class, 2); Array.set(array, 0, "blue"); Array.set(array, 1, "green"); printValue.invoke(object, array); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } }
运行结果:
blue green
引用块内容
[1]java核心技术 卷I
相关文章推荐
- eclipse中改变默认的workspace的方法及说明
- 《JAVA高级程序设计》第五周作业
- Spring IllegalArgumentException 异常
- 如何从spring官网下载jar包
- SpringMVC注解@RequestParam全面解析
- JMM(Java内存模型)中的核心概念
- Java技术_Java千百问(0029)_类、对象到底有什么秘密
- java如何异步方式处理业务逻辑
- eclipse快捷键
- java生成彩色附logo二维码
- Java代理模式
- Spring Mvc - 用户注册服务端生成默认头像实现
- MAVEN工程的构建与命令使用
- spring AOP动态代理使用和配置方式(手打)
- java不定长参数的简单使用
- 浅谈Java开发中的代理模式
- Java 父类,子类各自均有构造器和静态代码块 执行的顺序
- spring知识点积累
- 关于J2EE/EJB/Spring
- javah的使用常见错误