反射机制是 Java 的动态性之一
动态语言:在程序运行时,可以改变程序的结构或变量的类型
反射机制
程序在运行的过程中加载一些“只知道相关名字”的类,以下代码,在程序运行时加载 User 类。
Class c=Class.forName("cn.chb.User");
一个类被加载后,JVM 会创建一个对应类的 Class 对象,类的整个结构信息会被放到 Class 对象中。
这个 Class 对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。
反射机制的常见作用
1) 动态的加载类、动态的获取类的信息(属性,方法,构造器)
2) 动态构造对象
3) 动态调用类和对象的任意方法、构造器
4) 动态调用和处理属性
5) 获取泛型信息
6) 处理注解
获取 Class 对象的方式
1) 通过字节码文件
2) 对象的 getClass()方法
3) Class 类的静态方法 forName(….)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import com.bjsxt.entity.User; 2 3 public class Test { 4 public static void main(String[] args) throws ClassNotFoundException { 5 System.out.println(int.class); 6 System.out.println(void.class); 7 int []arrA=new int[10]; 8 int[] arrB=new int[30]; 9 /**维数相同和类型相同的数组共享同一个Class对象*/ 10 System.out.println(arrA.getClass()==arrB.getClass()); 11 12 /**同一个类的N多对象,共享同一个Class对象*/ 13 User u1=new User(); 14 User u2=new User(); 15 System.out.println(u1.getClass()==u2.getClass()); 16 17 18 /**获取Class对象的三种方式*/ 19 //(1)通过对象的getClass()方法获取 20 Class c1=u1.getClass(); 21 //(2)通过字节码文件获取 22 Class c2=User.class; 23 //(3)通过Class类的静态方法获取 24 Class c3=Class.forName("cn.chb.entity.User"); 25 26 System.out.println((c1==c2)+" "+(c1==c3)); 27 28 29 } 30 }
---------------------------------------------------------------------------
反射机制动态操作_方法_属性_构造器
获取类的名字
1 String getName() 获得包名+类名
2 String getSimpleName() 获得类的名字
获得类的属性
1 Field getField(String fieldName) 得到公共的属性对象
2 Field getDeclareField(String fieldName) 得到指定名称的属性对象
3 Field []c.getDeclaredFields() 得到所有的属性对象
获得类的方法
1 Method[] getDeclaredMethods() 得到公共的方法对象
2 Method[] c.getMethods() 得到父类及本类中的公共的方法对象
3 Method getDeclaredMethod(StringmethodName, Class …type)得到指定名称的本类中公共的方法
4 Method getMethod(String methodName,Class type)得到本类或父类中的公共的方法对象
获得构造方法
1 Constructor[] getDeclaredConstructors() 得到公共的构造方法的对象
2 Constructor [] getConstructors() 得到公共的构造方法对象
3 ConstructorgetDeclaredConstructor(Class...type)得到指定参数的公共的构造方法对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.lang.reflect.Constructor; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.Method; 4 5 public class Test { 6 public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, SecurityException, NoSuchMethodException { 7 String path="com.bjsxt.entity.User"; 8 //(1)获取类的名称 9 Class c=Class.forName(path); 10 System.out.println("类的全名称:"+c.getName());//类的全名称:cn.chb.entity.User 11 // System.out.println("类的名称:"+c.getSimpleName());/类的名称:User 12 13 //获取父类的Class对象 14 Class cSuper=c.getSuperclass(); 15 System.out.println(cSuper.getName());//java.lang.Object 16 System.out.println(cSuper.getSimpleName());//Object 17 18 //(2)获取类的属性信息 19 //Field f=c.getField("userId"); //只能获取公共的属性 20 //System.out.println(f); 21 Field [] fields=c.getFields(); //只能获取公共的属性 22 // System.out.println(fields.length);//0 23 24 Field [] fields2=c.getDeclaredFields(); 25 //System.out.println(fields2.length); 26 for (Field field : fields2) { 27 //System.out.println(field);//调用了toString()方法 28 // 权限 类型 全名 29 System.out.println(field.getModifiers()+" "+field.getType()+" "+field.getName()); 30 /*2 int userId 31 2 class java.lang.String userName 32 2 class java.lang.String password 33 */ 34 } 35 36 37 //(3)获取类的方法信息 38 Method[] methods=c.getDeclaredMethods(); //本类中的公共的方法对象 39 System.out.println(methods.length);//6 40 for (Method method : methods) { 41 //System.out.println(method); 42 System.out.println("访问权限"+method.getModifiers()); //1 43 System.out.println("返回值类型:"+method.getReturnType());//void 44 System.out.println("方法的名称:"+method.getName());//setUserName 45 //获取方法的参数 46 Class [] cPara=method.getParameterTypes(); 47 for (Class c1 : cPara) { 48 System.out.println(c1.getTypeName()+" "); 49 } 50 System.out.println(" --------------------------"); 51 52 } 53 System.out.println(" ============================= "); 54 55 //(4)获取类的构造器 56 Constructor [] cons=c.getConstructors(); 57 for (Constructor constructor : cons) { 58 System.out.println(constructor); 59 //public cn.chb.entity.User(int,java.lang.String,java.lang.String) 60 //public cn.chb.entity.User() 61 } 62 System.out.println(" ====================="); 63 //获取指定的构造方法 64 Constructor con=c.getConstructor(null); 65 System.out.println(con); 66 //public cn.chb.entity.User() 67 System.out.println(" ====================="); 68 Constructor con2=c.getConstructor(int.class,String.class,String.class); 69 System.out.println(con2); 70 //public cn.chb.entity.User(int,java.lang.String,java.lang.String) 71 } 72 }
提高反射效率
反射机制对程序的运行在性能上有一定的影响,速度慢
如何提高反射的性能
1) 通过 setAccessible 提高性能
a) setAccessible 启用和禁用访问安全检查的开关,值为true 则指示反射的对象在使用时应该取消 Java 语言访问检查,值为 false 则指示反射的对象不实施 Java 语
言访问检查,并不是为 true 就能访问为 false 就不能访问
b) 禁止安全检查,可以提高反射的运行速度
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import java.lang.reflect.InvocationTargetException; 2 import java.lang.reflect.Method; 3 4 public class Test { 5 public static void test01(){ 6 //User u=new User(); 7 Object obj=new Object(); 8 long startTime=System.currentTimeMillis(); 9 for(int i=0;i<1000000000L;i++){ 10 obj.hashCode(); 11 } 12 long endTime=System.currentTimeMillis(); 13 System.out.println("调用普通方法,执行10亿次:"+(endTime-startTime)+"ms"); 14 } 15 public static void test02() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ 16 Object obj=new Object(); 17 Class c=obj.getClass(); 18 //获取指定的方法 19 Method m=c.getDeclaredMethod("hashCode", null); 20 long startTime=System.currentTimeMillis(); 21 for(int i=0;i<1000000000L;i++){ 22 //执行这个方法 23 m.invoke(obj, null); 24 } 25 long endTime=System.currentTimeMillis(); 26 System.out.println("通过反射动态方法调用,执行10亿次:"+(endTime-startTime)+"ms"); 27 } 28 public static void test03() throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ 29 Object obj=new Object(); 30 Class c=obj.getClass(); 31 //获取指定的方法 32 Method m=c.getDeclaredMethod("hashCode", null); 33 34 m.setAccessible(true);//不执行安全检查 35 36 long startTime=System.currentTimeMillis(); 37 for(int i=0;i<1000000000L;i++){ 38 //执行这个方法 39 m.invoke(obj, null); 40 } 41 long endTime=System.currentTimeMillis(); 42 System.out.println("通过反射动态方法调用,不启用安全检查,执行10亿次:"+(endTime-startTime)+"ms"); 43 } 44 public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 45 test01(); 46 test02(); 47 test03(); 48 } 49 50 }