通过反射创建对象
- 通过反射创建对象有两种方式,一种通过Class对象的newInstance()方法,一种是获取到Class对象的Constructor后,再调用newInstance()方法,前者要求对应类有默认的无参构造器,后者则可以用特定的的构造器
- 前者用得较多,很多Java EE框架中都用xml配置文件信息来创建Java对象
- 示例:
package testpack;import java.lang.reflect.Constructor;public class Test1 { public static void main(String[] args)throws Exception{ Class clazz=A.class; Object obj1=clazz.newInstance(); //调用Class对象的newInstance()方法,用默认构造器创建 System.out.println(obj1); //输出:[name= default , age= 0 ] Constructor c=clazz.getConstructor(String.class,int.class); Object obj2=c.newInstance("Java",18); //调用Constructor的newInstance()方法用特定构造器创建 System.out.println(obj2); //输出:[name= Java , age= 18 ] }}class A{ private String name; public int age; A(){ name="default"; age=0; } public A(String name,int age){ this.name=name; this.age=age; } public String toString(){ return "[name= "+name+" , age= "+age+" ]"; }}
通过反射调用方法
- 获得一个Class对象的Method对象后,通过调用invoke(Object obj,Object...args)方法就可以调用特定对象的该方法了,obj就是该特定对象,args是要传入的实参
- 见示例:
package testpack;import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class Test1 { public static void main(String[] args)throws Exception{ Class clazz=A.class; //获取类A的Class对象 Constructor c=clazz.getConstructor(String.class,int.class); //获取构造方法 Object obj=c.newInstance("C++",28); //通过反射创建对象 Method m=clazz.getMethod("show",null); //获取名为show,无参的方法 m.invoke(obj,null); //在obj上调用show方法,传入参数为null,就无实参 }}class A{ private String name; public int age; A(){ name="default"; age=0; } public A(String name,int age){ this.name=name; this.age=age; } public String toString(){ return "[name= "+name+" , age= "+age+" ]"; } public void show(){ System.out.println("现在在调用show()方法,我是:"+toString()); }}
通过反射访问成员变量
- 获取成员变量的值用get(Objcet obj)、getInt(Object obj)、getLong(Object obj)、...以此类推
- 设置成员变量的值用set(Objcet obj)、setInt(Objcet obj)、setLong(Objcet obj)、...以此类推
- 如果是private修饰的变量,在访问之前用setAccessible(true)取消访问权限检查
- 见示例:
package testpack;import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class Test1 { public static void main(String[] args)throws Exception{ Class clazz=A.class; Constructor c=clazz.getConstructor(String.class,int.class); Object obj=c.newInstance("C++",28); System.out.println(obj); //输出:[name= C++ , age= 28 ] Field nameField=clazz.getDeclaredField("name"); //获得name这个private成员变量 nameField.setAccessible(true); //取消对该变量的访问权限检查 System.out.println("private name="+nameField.get(obj)); //输出:private name=C++ Field ageField=clazz.getField("age"); //获得age这个public成员变量 System.out.println("public age= "+ageField.getInt(obj)); //输出:public age= 28 nameField.set(obj,"Java"); //将obj的private的name变量改为“Java” ageField.setInt(obj, 100); //将obj的public的age变量改为100 System.out.println("修改了对象的private和public实例变量:"+obj); //输出:修改了对象的private和public实例变量:[name= Java , age= 100 ] }}class A{ private String name; public int age; A(){ name="default"; age=0; } public A(String name,int age){ this.name=name; this.age=age; } public String toString(){ return "[name= "+name+" , age= "+age+" ]"; } }
- setAccessible()方法是Constructor、Field、Method的父类的AccessibleObject的方法,因此这三个类都可以用
- 见示例:
package testpack;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class Test1 { public static void main(String[] args)throws Exception{ Class clazz=A.class; Constructor c=clazz.getDeclaredConstructor(String.class,int.class); c.setAccessible(true); //取消该构造器的访问权限检查 Object obj=c.newInstance("Java",18); //调用私有构造器 System.out.println(obj); Method m=clazz.getDeclaredMethod("show",null); m.setAccessible(true); //取消show()方法的访问权限检查 m.invoke(obj, null); //调用私有方法 }}class A{ private String name; public int age; A(){ name="default"; age=0; } private A(String name,int age){ //private构造器 this.name=name; this.age=age; System.out.println("调用了private构造器"); } public String toString(){ return "[name= "+name+" , age= "+age+" ]"; } private void show(){ //private方法 System.out.println("在调用private方法:"+toString()); }}
通过反射操作数组
- java.lang.reflect.Array可用来操作数组
- 创建一个数组:
- static Object newInstance(Class<?>componentType,int...length):两个参数一个是类型,一个是长度
- 访问某个数组元素:
- static xxx getXxx(Object array,int index):返回array数组的第index个元素;引用类型则是:get(Object array,int index)
- 设置某个数组元素的值
- static void setXxx(Object array,int index,xxx value):设置数组array元素的第index个元素的值为value,引用类型:set(....)
- 获取数组的长度
- static int getLength(Object array):获得数组array的长度
- 见示例:
package testpack;import java.lang.reflect.Array;public class Test1 { public static void main(String[] args)throws Exception{ Object arr=Array.newInstance(String.class, 5); //调用构造方法 Array.set(arr, 0, "Java"); //将索引号为0的元素设置为“Java” Array.set(arr, 1, "C++"); Array.set(arr, 2, "python"); System.out.println(Array.get(arr, 2)); //取得索引号为2的元素 System.out.println("array的长度:"+Array.getLength(arr)); //输出:array的长度:5 }}