Java反射机制(Reflection)

时间:2022-10-26 21:18:17

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 }

 运行结果:

Java反射机制(Reflection)Java反射机制(Reflection)
---------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)
View Code

从上面示例中可以看出,要想使用反射的第一步就是获取要操作类所对应的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对象中的方法