在编译过程中,无法预知该对象,类或者可能属于那些类,只能依靠程序运行时信息来发现该对象和类的真实信息,而从程序运行过程中,实现程序运行时获取对象和类的信息,这就是反射
获取类
通过反射获取类的方法有如下:
public class Test { public int a; public int b; private int c; private int d; public String aa; private String bb; public Test(){} public Test(int a,int b,int c,int d){ this.a=a; this.b=b; this.c=c; this.d=d; } private Test(int c,int d){ this.c=c; this.d=d; } public int getA() { return a; } public void setA(int a) { this.a = a; } public int getB() { return b; } public void setB(int b) { this.b = b; } public int getC() { return c; } public void setC(int c) { this.c = c; } public int getD() { return d; } public void setD(int d) { this.d = d; } private void A(){ System.out.println("哈哈哈"); } public void B(){ System.out.println("fdsa"); } @Override public String toString() { return "Test [a=" + a + ", b=" + b + ", c=" + c + ", d=" + d + ", aa=" + aa + ", bb=" + bb + "]"; } }
Class<?> class_1 = Class.forName("Test"); //方法一,使用Class类的forName(String clazzName)静态方法 Class<?> class_2 = Test.class; //方法二,调用类的class属性获取该类的对应Class对象 Test test = new Test(); Class<?> testClass = test.getClass(); //方法三,调用某个对象的getClass()方法。
其中,方法一和方法二都是直接根据类来取得该类的class对象,方法三则是通过类的对象取得该类的class对象。
方法一和方法二相比之下,方法二较有优势:1,代码更安全,编译时可以;2,程序性能更好,因为无需调用方法;
获取类信息
1. 获取类的构造方法(构造器)
//获取用public修饰指定参数的构造方法,如要获取默认构造方法,参数为Test.class Constructor<?> constructor_1 = Test.class.getConstructor(Test.class); //getConstructor(Class<?>...parameterTypes) //获取所有用public修饰的构造方法 Constructor<?>[] constructor_2 = Test.class.getConstructors(); //getConstructors() //获取指定参数的构造方法 Constructor<?> constructor_3 = Test.class.getDeclaredConstructor(); //getDeclaredConstructor(Class<?>...parameterTypes); //获取所有的构造方法 Constructor<?>[] constructor_4 = Test.class.getDeclaredConstructors(); //getDeclaredConstructors
2. 获取类的属性
//获取public修饰并指定的属性名 Field feild_1 = Test.class.getField("a"); //getField(String name); //获取public修饰的所有属性名 Field[] feild_2 = Test.class.getFields(); //getFields(); //获取指定的属性名 Field feild_3 = Test.class.getDeclaredField("c"); //getDeclaredField(String name); //获取所有的属性名 Field[] feild_4 = Test.class.getDeclaredFields(); //getDeclaredFields();
3. 获取类的方法
//获取public修饰并指定的方法 Method method_1 = Test.class.getMethod("getA"); //getMethod(String name,Class<?>...parameterTypes); //获取public修饰的所有方法
Method[] method_2 = Test.class.getMethods(); //getMethods() //获取指定的方法 Method method_3 = Test.class.getDeclaredMethod("A"); //getDeclaredMethod(String name,Class<?>...parameterTypes); //获取所有的方法
Method[] method_4 = Test.class.getDeclaredMethods(); //getDeclaredMethods()
使用反射生成并操作对象
1. 创建对象
//创建默认构造方法的对象(无默认构造方法则报错) Object test_1 = Test.class.newInstance(); //创建指定构造方法的对象(可以是默认构造方法)
Constructor<?> constructor = Test.class.getDeclaredConstructor(int.class,int.class,int.class,int.class); Object test_2 = constructor.newInstance(1,3,4,5);
2. 调用方法
Object obj = method_1.invoke(test_1); //method.invoke(Object obj,Object...parameterTypes) 第一个参数为对应类的对象,第二个参数为该方法的参数
3. 访问属性值
Test test = new Test(); //获取对象 Field fieldI = Test.class.getDeclaredField("c"); //获取私有属性c Field fieldII = Test.class.getField("aa"); //获取属性aa Field fieldIII = Test.class.getDeclaredField("bb"); //获取私有属性bb fieldI.setAccessible(true); //解除访问限制
fieldI.setInt(test,1); //八大基本数据类型设置属性 方法一 setXxx(Object obj,Xxx val) Xxx指八大基本数据类型,其中首字母大写
Object obj_1 = fieldI.getInt(test); //八大基本数据类型获取属性 方法一 getXxx(Object obj,Xxx val) Xxx指八大基本数据类型,其中首字母大写
System.out.println(obj_1);
fieldI.set(test,12); //八大基本数据类型设置属性 方法二 set(Object obj,Obj val)
Object obj_2 = fieldI.get(test); //八大基本数据类型获取属性 方法二 get(Object obj)
System.out.println(obj_2);
fieldII.set(test,"Test"); //复合数据类型设置属性 set(Object obj,Obj val)
Object obj_3 = fieldII.get(test); //复合数据类型获取属性 get(Object obj)
System.out.println(obj_3);
System.out.println(test);
fieldIII.set(test,"哈哈");
System.out.println(test);
全部代码:
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class TestMain { public static void main(String[] args){ try { Class<?> class_1 = Class.forName("Test"); //方法一 Class<?> class_2 = Test.class; //方法二 // Test test = new Test(); // Class<?> class_3 = test.getClass(); //方法三 System.out.println("--------类----------"); System.out.println("1"+class_1); System.out.println("2"+class_2); // System.out.println("3"+class_3); Constructor<?> constructor_1 = Test.class.getConstructor(); Constructor<?>[] constructor_2 = Test.class.getConstructors(); Constructor<?> constructor_3 = Test.class.getDeclaredConstructor(); Constructor<?>[] constructor_4 = Test.class.getDeclaredConstructors(); System.out.println("--------构造方法----------"); System.out.println(constructor_1); System.out.println(constructor_2); System.out.println(constructor_3); System.out.println(constructor_4); //获取public修饰并指定的属性名 Field feild_1 = Test.class.getField("a"); //getField(String name); //获取public修饰的所有属性名 Field[] feild_2 = Test.class.getFields(); //getFields(); //获取指定的属性名 Field feild_3 = Test.class.getDeclaredField("c"); //getDeclaredField(String name); //获取所有的属性名 Field[] feild_4 = Test.class.getDeclaredFields(); //getDeclaredFields(); System.out.println("--------类的属性----------"); System.out.println(feild_1); System.out.println(feild_2); System.out.println(feild_3); System.out.println(feild_4); //获取public修饰并指定的方法 Method method_1 = Test.class.getMethod("getA"); //getMethod(String name,Class<?>...parameterTypes); //获取public修饰的所有方法 Method[] method_2 = Test.class.getMethods(); //getMethods() //获取指定的方法 Method method_3 = Test.class.getDeclaredMethod("A"); //getDeclaredMethod(String name,Class<?>...parameterTypes); //获取所有的方法 Method[] method_4 = Test.class.getDeclaredMethods(); //getDeclaredMethods() System.out.println("--------类的方法----------"); System.out.println(method_1); System.out.println(method_2); System.out.println(method_3); System.out.println(method_4); //创建默认构造方法的对象(无默认构造方法则报错) Object test_1 = Test.class.newInstance(); //创建指定构造方法的对象(可以是默认构造方法) Constructor<?> constructor = Test.class.getDeclaredConstructor(int.class,int.class,int.class,int.class); Object test_2 = constructor.newInstance(1,3,4,5); System.out.println("--------创建对象----------"); System.out.println(test_1); System.out.println(test_2); Object obj = method_1.invoke(test_1); System.out.println("--------方法调用----------"); System.out.println(obj); Test test = new Test(); Field fieldI = Test.class.getDeclaredField("c"); Field fieldII = Test.class.getField("aa"); Field fieldIII = Test.class.getDeclaredField("bb"); fieldI.setAccessible(true); System.out.println("--------属性访问----------"); fieldI.setInt(test,1); //八大基本数据类型设置属性 方法一 setXxx(Object obj,Xxx val) Xxx指八大基本数据类型,其中首字母大写 Object obj_1 = fieldI.getInt(test); //八大基本数据类型获取属性 方法一 getXxx(Object obj,Xxx val) Xxx指八大基本数据类型,其中首字母大写 System.out.println(obj_1); fieldI.set(test,12); //八大基本数据类型设置属性 方法二 set(Object obj,Obj val) Object obj_2 = fieldI.get(test); //八大基本数据类型获取属性 方法二 get(Object obj) System.out.println(obj_2); fieldII.set(test,"Test"); //复合数据类型设置属性 set(Object obj,Obj val) Object obj_3 = fieldII.get(test); //复合数据类型获取属性 get(Object obj) System.out.println(obj_3); System.out.println(test); fieldIII.set(test,"哈哈"); System.out.println(test); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }