Java反射机制(Reflection)
Java反射机制(Reflection)
一、反射机制是什么
Java反射机制是程序在运行过程中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性,这种动态获取类信息以及动态调用对象方法的功能就是JAVA语言的反射机制。
二、反射机制能干什么
(1)在运行时判断任意一个对象所属的类
(2)在运行时构造任意一个类的对象
(3)在运行时判断任意一个类所具有的成员变量和方法
(4)在运行时调用任意一个对象的方法
(PS:注意反射机制都是在程序运行时,而不是在编译时。)
反射机制允许程序在运行时透过JDK提供的反射API获取任意一个已知名称的class的内部消息,包括: 修饰符、父类、接口、属性、构造方法、方法 等所有的信息,并可在程序运行时改变属性的值或者调用方法。
三、JDK提供的反射机制中的类
在JDK中主要由以下类来实现Java的反射机制,这些类都位于java.lang.reflect包中(Class类除外):
java.lang.Class: 代表一个类
java.lang.reflect.Constructor:代表类的构造方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Modifier:代表修饰符
java.lang.reflect.Array:提供动态创建数组,以及访问数组的元素的静态方法
四、利用示例对反射机制的使用进行初步体会
示例一:
利用反射机制打印java.lang.String类中所有的属性、构造方法、方法
1 /** 2 *利用反射机制打印String类中的所方法信息 3 * @author Administrator 4 * 5 */ 6 public class ObjectReflectDemo { 7 public static void main(String[] args) throws Exception { 8 //反射的第一步是获取要操作的类所对应的Class对象 9 Class<?> cls = Class.forName("java.lang.String"); 10 System.out.println("---------String类中的属性:---------------------"); 11 12 Field[] fields = cls.getDeclaredFields(); 13 for(Field f : fields){ 14 System.out.println(f); 15 } 16 System.out.println("---------String类中的构造方法:--------------------"); 17 Constructor[] contructors = cls.getDeclaredConstructors(); 18 for(Constructor c : contructors){ 19 System.out.println(c); 20 } 21 System.out.println("---------String类中的方法:---------------------"); 22 Method[] methods = cls.getDeclaredMethods(); 23 for(Method m : methods){ 24 System.out.println(m); 25 } 26 } 27 }
运行结果:
---------String类中的属性:--------------------- private final char[] java.lang.String.value private int java.lang.String.hash private static final long java.lang.String.serialVersionUID private static final java.io.ObjectStreamField[] java.lang.String.serialPersistentFields public static final java.util.Comparator java.lang.String.CASE_INSENSITIVE_ORDER private static final int java.lang.String.HASHING_SEED private transient int java.lang.String.hash32 ---------String类中的构造方法:-------------------- public java.lang.String(byte[]) public java.lang.String(byte[],int,int) public java.lang.String(byte[],java.nio.charset.Charset) public java.lang.String(byte[],java.lang.String) throws java.io.UnsupportedEncodingException public java.lang.String(byte[],int,int,java.nio.charset.Charset) java.lang.String(int,int,char[]) java.lang.String(char[],boolean) public java.lang.String(java.lang.StringBuilder) public java.lang.String(java.lang.StringBuffer) public java.lang.String(int[],int,int) public java.lang.String(char[],int,int) public java.lang.String(char[]) public java.lang.String(java.lang.String) public java.lang.String() public java.lang.String(byte[],int,int,java.lang.String) throws java.io.UnsupportedEncodingException public java.lang.String(byte[],int) public java.lang.String(byte[],int,int,int) ---------String类中的方法:--------------------- public boolean java.lang.String.equals(java.lang.Object) public java.lang.String java.lang.String.toString() public int java.lang.String.hashCode() public int java.lang.String.compareTo(java.lang.String) public int java.lang.String.compareTo(java.lang.Object) public int java.lang.String.indexOf(int) public int java.lang.String.indexOf(java.lang.String,int) public int java.lang.String.indexOf(java.lang.String) public int java.lang.String.indexOf(int,int) static int java.lang.String.indexOf(char[],int,int,char[],int,int,int) public static java.lang.String java.lang.String.valueOf(double) public static java.lang.String java.lang.String.valueOf(char[],int,int) public static java.lang.String java.lang.String.valueOf(float) public static java.lang.String java.lang.String.valueOf(java.lang.Object) public static java.lang.String java.lang.String.valueOf(long) public static java.lang.String java.lang.String.valueOf(char[]) public static java.lang.String java.lang.String.valueOf(boolean) public static java.lang.String java.lang.String.valueOf(char) public static java.lang.String java.lang.String.valueOf(int) public char java.lang.String.charAt(int) private static void java.lang.String.checkBounds(byte[],int,int) public int java.lang.String.codePointAt(int) public java.lang.String java.lang.String.concat(java.lang.String) public boolean java.lang.String.contains(java.lang.CharSequence) public static java.lang.String java.lang.String.copyValueOf(char[]) public static java.lang.String java.lang.String.copyValueOf(char[],int,int) public boolean java.lang.String.endsWith(java.lang.String) public static java.lang.String java.lang.String.format(java.util.Locale,java.lang.String,java.lang.Object[]) public static java.lang.String java.lang.String.format(java.lang.String,java.lang.Object[]) public byte[] java.lang.String.getBytes() public byte[] java.lang.String.getBytes(java.nio.charset.Charset) public byte[] java.lang.String.getBytes(java.lang.String) throws java.io.UnsupportedEncodingException public void java.lang.String.getBytes(int,int,byte[],int) public void java.lang.String.getChars(int,int,char[],int) void java.lang.String.getChars(char[],int) public int java.lang.String.codePointBefore(int) public int java.lang.String.codePointCount(int,int) public int java.lang.String.compareToIgnoreCase(java.lang.String) public boolean java.lang.String.contentEquals(java.lang.CharSequence) public boolean java.lang.String.contentEquals(java.lang.StringBuffer) public boolean java.lang.String.equalsIgnoreCase(java.lang.String) private int java.lang.String.indexOfSupplementary(int,int) private int java.lang.String.lastIndexOfSupplementary(int,int) public int java.lang.String.offsetByCodePoints(int,int) int java.lang.String.hash32() public native java.lang.String java.lang.String.intern() public boolean java.lang.String.isEmpty() public int java.lang.String.lastIndexOf(java.lang.String,int) static int java.lang.String.lastIndexOf(char[],int,int,char[],int,int,int) public int java.lang.String.lastIndexOf(int,int) public int java.lang.String.lastIndexOf(int) public int java.lang.String.lastIndexOf(java.lang.String) public int java.lang.String.length() public boolean java.lang.String.matches(java.lang.String) public java.lang.String java.lang.String.replace(java.lang.CharSequence,java.lang.CharSequence) public java.lang.String java.lang.String.replace(char,char) public java.lang.String java.lang.String.replaceAll(java.lang.String,java.lang.String) public java.lang.String java.lang.String.replaceFirst(java.lang.String,java.lang.String) public java.lang.String[] java.lang.String.split(java.lang.String,int) public java.lang.String[] java.lang.String.split(java.lang.String) public boolean java.lang.String.startsWith(java.lang.String) public boolean java.lang.String.startsWith(java.lang.String,int) public java.lang.CharSequence java.lang.String.subSequence(int,int) public java.lang.String java.lang.String.substring(int) public java.lang.String java.lang.String.substring(int,int) public char[] java.lang.String.toCharArray() public java.lang.String java.lang.String.toLowerCase(java.util.Locale) public java.lang.String java.lang.String.toLowerCase() public java.lang.String java.lang.String.toUpperCase(java.util.Locale) public java.lang.String java.lang.String.toUpperCase() public java.lang.String java.lang.String.trim() public boolean java.lang.String.regionMatches(int,java.lang.String,int,int) public boolean java.lang.String.regionMatches(boolean,int,java.lang.String,int,int)
从上面示例中可以看出,要想使用反射的第一步就是获取要操作类所对应的Class对象,一共有三种方法:
第一种: 调用Class类的静态方法forName,比如 Class.forName("java.lang.String")
第二种: 使用类的.class语法,比如 : Class cls = String.class
第三种: 调用对象的getClass方法, 比如:String str = "123"; Class cls = str.getClass();(PS:在java.lang.Object类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型)
示例二:
1 import java.lang.reflect.Field; 2 import java.lang.reflect.Method; 3 4 /** 5 * 要求: 6 * 1.通过反射的方式调用add方法 7 * 2.通过反射的方式调用getNum方法 8 * 3.通过反射的反射修改num属性的值为55,再通过反射的方式调用getNum方法 9 * @author Administrator 10 * 11 */ 12 public class ReflectTest { 13 private int num = 2; 14 15 public int add(int a,int b){ 16 return a+b; 17 } 18 19 public int getNum() { 20 return num; 21 } 22 23 public static void main(String[] args) throws Exception { 24 //第一步: 获取ReflectTest类所对应的Class对象 25 Class<?> cls = Class.forName("ReflectTest"); 26 //第二步:通过Class类的newInstance()方法来创建ReflectTest类的一个对象 27 Object obj = cls.newInstance(); 28 29 //第步:通过Class的getDeclaredMethod(String name, Class<?>... parameterTypes)获取ReflectTest类中指定的方法 30 Method addMethod = cls.getDeclaredMethod("add", new Class[]{int.class,int.class}); 31 Method getNumMethod = cls.getDeclaredMethod("getNum", new Class[]{}); 32 33 //第四部:通过Method类的invoke(Object obj, Object... args)方法来反射调用ReflectTest类中指定的方法 34 //4.1通过反射调用add方法 35 int addResult = (int)addMethod.invoke(obj, new Object[]{11,22}); 36 System.out.println("addResult = " + addResult); 37 38 //4.2通过反射的方式调用getNum方法 39 int returnNum1 = (int)getNumMethod.invoke(obj, new Object[]{}); 40 System.out.println("returnNum1 = " + returnNum1); 41 42 //4.3通过反射的反射修改num属性的值为55,再通过反射的方式调用getNum方法 43 Field field = cls.getDeclaredField("num"); 44 field.set(obj, 55); 45 int returnNum2 = (int)getNumMethod.invoke(obj, new Object[]{}); 46 System.out.println("returnNum2 = " + returnNum2); 47 } 48 }
通过上面的2个示例,可以看出:
(1)反射的第一步是获取要操作的类所对应的Class对象(有三种方式)
(2)类中每一个方法对应着一个java.lang.reflect.Method对象
(3)类中每一个属性对应着一个java.lang.reflect.Field对象
五、使用java反射机制,需要遵循的三步
第一步:获取要操作的类所对应的Class对象,得到该Class对象后就可以获取想要操作类的所有信息。(具体参考java.lang.Class API)
第二步: 通过Class对象去获取操作类的属性、构造方法、方法 所分别对应的Field、Constructor、Method的对象
第三步: 调用Field、Constructor、Method对象中的方法