JAVA反射学习
1.Class类
1 package com.hxy; 2 3 class Foo{} 4 5 public class Reflect 6 { 7 public static void main(String[] args) 8 { 9 //1.获取Class对象 10 Class c1 = Foo.class; 11 12 Class c2 = new Foo().getClass(); 13 14 Class c3 = null; 15 try 16 { 17 c3 = Class.forName("com.hxy.Foo"); 18 } 19 catch (ClassNotFoundException e) 20 { 21 e.printStackTrace(); 22 } 23 24 System.out.println(c1 == c2); 25 System.out.println(c2 == c3); 26 //true 27 //true 28 29 //2.通过类的Class对象创建该类实例 30 try 31 { 32 //调用newInstance方法需要Foo类有无参数的构造方法 33 Foo foo1 = (Foo) c1.newInstance(); 34 } 35 catch (InstantiationException e) 36 { 37 e.printStackTrace(); 38 } catch (IllegalAccessException e) 39 { 40 e.printStackTrace(); 41 } 42 43 //3.动态加载类 44 45 //编译时刻加载类是“静态加载类” 46 //运行时刻加载类是“动态加载类” 47 48 //new创建对象是“静态加载类”,编译时刻就需要加载所有可能使用的类,无论是否可能用到 49 50 //Class.forName("完整类名")是动态加载类,要动态加载的类会在运行时加载 51 //好处:动态加载的类可以随意添加或者更改,而不需要编译此文件 52 53 //基本数据类型也有对应的Class 54 Class c4 = int.class; 55 Class c5 = Integer.class; 56 System.out.println(c4 == c5); 57 //false 58 59 //注:基本的数据类型和void都存在相应的Class对象 60 Class c6 = void.class; 61 62 //getName()获取类全称 63 //getSimpleName获取不包含包名的类的名称 64 System.out.println(c4.getName()); 65 System.out.println(c5.getName()); 66 System.out.println(c6.getName()); 67 //int 68 //java.lang.Integer 69 //void 70 } 71 }
2.获取类的成员变量、方法以及构造函数信息
ClassUtil.java:
1 package com.hxy; 2 import java.lang.reflect.Constructor; 3 import java.lang.reflect.Field; 4 import java.lang.reflect.Method; 5 6 public class ClassUtil 7 { 8 public static void printFieldMessage(Object obj) 9 { 10 Class c = obj.getClass(); 11 System.out.println("类的名称是:" + c.getName()); 12 System.out.println("获取成员变量列表:"); 13 //getFields()方法获取的是所有public的成员变量,包括继承而来的 14 //getDeclaredFields()方法获取的是所有该类自己声明的成员变量,不论访问权限 15 Field[] fields = c.getDeclaredFields(); 16 for(int i = 0; i < fields.length; i++) 17 { 18 Class fieldType = fields[i].getType(); 19 String typeName = fieldType.getName(); 20 String fieldName = fields[i].getName(); 21 System.out.println(typeName + " " + fieldName); 22 } 23 System.out.println("获取成员变量列表结束。"); 24 } 25 26 public static void printMethodMessage(Object obj) 27 { 28 Class c = obj.getClass(); 29 System.out.println("类的名称是:" + c.getName()); 30 //getMethods()方法获取的是所有public的函数,包括继承而来的 31 //getDeclaredMethods()方法获取的是所有该类自己声明的方法,不论访问权限 32 Method[] methods = c.getMethods(); 33 System.out.println("获取方法列表:"); 34 for(Method m: methods) 35 { 36 Class returnType = m.getReturnType(); 37 System.out.print(returnType.getName() + " " + m.getName() + "("); 38 Class[] paramTypes = m.getParameterTypes(); 39 for(int i = 0; i < paramTypes.length; i++) 40 { 41 String info = paramTypes[i].getName(); 42 if(i != paramTypes.length - 1) 43 { 44 info = info + ", "; 45 } 46 System.out.print(info); 47 } 48 System.out.println(")"); 49 } 50 System.out.println("获取方法列表结束。"); 51 } 52 53 public static void printConstructorMessage(Object obj) 54 { 55 Class c = obj.getClass(); 56 System.out.println("类的名称是:" + c.getName()); 57 System.out.println("获取构造函数列表:"); 58 Constructor[] constructors = c.getDeclaredConstructors(); 59 for(Constructor constructor: constructors) 60 { 61 System.out.print(constructor.getName() + "("); 62 Class[] paramTypes = constructor.getParameterTypes(); 63 for(int i = 0; i < paramTypes.length; i++) 64 { 65 String info = paramTypes[i].getName(); 66 if(i != paramTypes.length - 1) 67 { 68 info = info + ", "; 69 } 70 System.out.print(info); 71 } 72 System.out.println(")"); 73 } 74 System.out.println("获取构造函数列表结束。"); 75 } 76 }
ClassUtilTest.java:
1 package com.hxy; 2 3 public class ClassUtilTest 4 { 5 public static void main(String[] args) 6 { 7 Integer integer = 6; 8 ClassUtil.printMethodMessage(integer); 9 System.out.println("<------------------->"); 10 ClassUtil.printFieldMessage(integer); 11 System.out.println("<------------------->"); 12 ClassUtil.printConstructorMessage(integer); 13 } 14 }
运行结果:
1 类的名称是:java.lang.Integer 2 获取方法列表: 3 int numberOfLeadingZeros(int) 4 int numberOfTrailingZeros(int) 5 int bitCount(int) 6 boolean equals(java.lang.Object) 7 java.lang.String toString(int, int) 8 java.lang.String toString() 9 java.lang.String toString(int) 10 int hashCode(int) 11 int hashCode() 12 int min(int, int) 13 int max(int, int) 14 int reverseBytes(int) 15 int compareTo(java.lang.Integer) 16 int compareTo(java.lang.Object) 17 byte byteValue() 18 short shortValue() 19 int intValue() 20 long longValue() 21 float floatValue() 22 double doubleValue() 23 java.lang.Integer valueOf(java.lang.String, int) 24 java.lang.Integer valueOf(int) 25 java.lang.Integer valueOf(java.lang.String) 26 java.lang.String toHexString(int) 27 int compare(int, int) 28 java.lang.Integer decode(java.lang.String) 29 int reverse(int) 30 int sum(int, int) 31 int parseInt(java.lang.String) 32 int parseInt(java.lang.String, int) 33 long toUnsignedLong(int) 34 int compareUnsigned(int, int) 35 int divideUnsigned(int, int) 36 java.lang.Integer getInteger(java.lang.String, java.lang.Integer) 37 java.lang.Integer getInteger(java.lang.String, int) 38 java.lang.Integer getInteger(java.lang.String) 39 int highestOneBit(int) 40 int lowestOneBit(int) 41 int parseUnsignedInt(java.lang.String) 42 int parseUnsignedInt(java.lang.String, int) 43 int remainderUnsigned(int, int) 44 int rotateLeft(int, int) 45 int rotateRight(int, int) 46 int signum(int) 47 java.lang.String toBinaryString(int) 48 java.lang.String toOctalString(int) 49 java.lang.String toUnsignedString(int) 50 java.lang.String toUnsignedString(int, int) 51 void wait() 52 void wait(long, int) 53 void wait(long) 54 java.lang.Class getClass() 55 void notify() 56 void notifyAll() 57 获取方法列表结束。 58 <-------------------> 59 类的名称是:java.lang.Integer 60 获取成员变量列表: 61 int MIN_VALUE 62 int MAX_VALUE 63 java.lang.Class TYPE 64 [C digits 65 [C DigitTens 66 [C DigitOnes 67 [I sizeTable 68 int value 69 int SIZE 70 int BYTES 71 long serialVersionUID 72 获取成员变量列表结束。 73 <-------------------> 74 类的名称是:java.lang.Integer 75 获取构造函数列表: 76 java.lang.Integer(int) 77 java.lang.Integer(java.lang.String) 78 获取构造函数列表结束。
3.方法的反射
1 package com.hxy; 2 import java.lang.reflect.Method; 3 4 class A 5 { 6 public void print(int a, int b) 7 { 8 System.out.println(a + b); 9 } 10 } 11 12 public class MethodReflect 13 { 14 public static void main(String[] args) 15 { 16 A obj = new A(); 17 Class c = obj.getClass(); 18 try 19 { 20 //正常方法调用 21 obj.print(10, 20); 22 23 //方法的反射 24 Method m = c.getMethod("print", int.class, int.class); 25 m.invoke(obj, 10, 20); 26 } 27 catch (Exception e) 28 { 29 e.printStackTrace(); 30 } 31 } 32 }
运行结果:
1 30 2 30
一个简单的例子体现方法反射的优越性:
UserService.java:
1 package com.hxy; 2 3 public class UserService 4 { 5 public void delete() 6 { 7 System.out.println("Delete Service Starts"); 8 } 9 10 public void update() 11 { 12 System.out.println("Update Service Starts"); 13 } 14 15 public void find() 16 { 17 System.out.println("Find Service Starts"); 18 } 19 }
UserServiceInterface.java:
1 package com.hxy; 2 import java.io.BufferedReader; 3 import java.io.InputStreamReader; 4 import java.lang.reflect.Method; 5 6 public class UserServiceInterface 7 { 8 public static void main(String[] args) 9 { 10 UserService us = new UserService(); 11 try 12 { 13 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 14 System.out.print("Please Input Your Operation: "); 15 String action = br.readLine(); 16 /* 17 常规写法(不符合开闭原则) 18 if("update".equals(action)) 19 { 20 us.update(); 21 } 22 if("delete".equals(action)) 23 { 24 us.delete(); 25 } 26 if("find".equals(action)) 27 { 28 us.find(); 29 } 30 */ 31 //运用反射的优雅写法 32 Class c = us.getClass(); 33 Method m = c.getMethod(action); 34 m.invoke(us); 35 } 36 catch (Exception e) 37 { 38 System.out.println("No Such Service!"); 39 } 40 } 41 }
*:Hibernate等持久层框架中的万能DAO层实现就是基于方法的反射。
4.从反射理解泛型
1 package com.hxy; 2 import java.lang.reflect.Method; 3 import java.util.ArrayList; 4 5 public class GenericReflect 6 { 7 public static void main(String[] args) 8 { 9 ArrayList<String> list1 = new ArrayList<String>(); 10 ArrayList<Integer> list2 = new ArrayList<Integer>(); 11 Class c1 = list1.getClass(); 12 Class c2 = list2.getClass(); 13 System.out.println(c1 == c2); 14 //true 15 16 //结论: 17 //反射的操作实际上是编译之后的操作 18 //.class 19 //集合泛型,是用来防止错误输入的,只在编译阶段有效 20 21 //验证: 22 try 23 { 24 System.out.println(list1.size()); 25 //0 26 Method m = c1.getMethod("add", Object.class); 27 //add一个数字而不是string 28 m.invoke(list1, 666); 29 System.out.println(list1.size()); 30 //1 31 //所以说:反射的操作实际上是编译之后的操作,不受编译阶段检查 32 //且泛型只在编译阶段有效 33 } 34 catch(Exception e) 35 { 36 e.printStackTrace(); 37 } 38 } 39 }