反射
使用反射经常要用到的类,位于java.lang.reflect包中。
--Class类:代表一个类
--Field类:代表类的成员变量
--Method类:代表类的方法
--Constructor类:代表类的构造方法
--Array类:提供一个动态创建的数组,以及访问数组元素的静态方法。
使用Method类
public class RefletTest { public static void main(String[] args) throws Exception { Class<?> classType = Class.forName("java.lang.String"); //getDeclaredMethods获得对应类的所有方法,包括private的 Method[] methods =
classType.getDeclaredMethods(); for(Method method : methods) { System.out.println(method); } } } |
使用反射进行方法的调用
public class InvokeTester { public int add(int a,int b) { return a + b; } public void output(String msg) { System.out.println(msg); } public static void main(String[] args) throws Exception { //取得自定义类的类型 Class<?> classType =
InvokeTester.class; //创建自定义的一个实例 Object invokeTester =
classType.newInstance(); //取得自定义类的一个方法 Method addMethod = classType.getMethod("add", new Class[]{int.class, int.class }); //调用自定义类的实例的方法 Object result =
addMethod.invoke(invokeTester, new Object[]{1, 2}); System.out.println(result); Method outputMethod =
classType.getMethod("output",new Class[]{String.class}); outputMethod.invoke(invokeTester,new Object[]{"Hello"}); System.out.println(Object.class); } } |
要使用反射,首先需要获得待处理类或对象所对应的Class对象。
获取某个类或某个对象对应的Class对象的常用的3种方式:
a.使用Class类的静态方法forName.如Class.forName(“java.lang.String”);
b.使用类的.class语法:String.class
c.使用对象的getClass()方法:String s = “a”; Class<?> clazz =
s.getClass();
public class ClassTest { public static void main(String[] args) { Class<?>
classType = Child.class; System.out.println(classType); classType = classType.getSuperclass(); System.out.println(classType); classType = classType.getSuperclass(); System.out.println(classType); classType = classType.getSuperclass(); System.out.println(classType); } } class Parent { } class Child extends Parent { } |
Constructor类的使用
若想调用类的不带参数的构造方法来生成对象,我们有两种方法:
a.
先获得Class对象,然后通过该Class对象的newInstance()方法直接生成即可。
Class<?>
clazz = String.class; Object object = clazz.newInstance(); |
b.
先获得Class对象,然后通过该对象获得对应的Constructor对象,再通过该Constructor对象的newInstance方法生成:
Class<?>
clazz = Customer.class; Constructor cons
= clazz.getConstructor(new Class[]{}); Object obj = cons.newsInstance(new Object[]{}); |
若想调用类的带参数的构造方法,可以用如下方式:
Class<?>
clazz = Customer.class; Constructor cons
= clazz.getConstructor(new Class[]{String.class,int.class}); Object obj = cons.newsInstance(new
Object[]{“jack”,23}); |
public class Customer { private long Id; private String name; private int age; public Customer() { } public Customer(String name, int age) { this.name = name ; this.age = age; } public long getId() { return Id; } public void setId(long id) { Id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } public class ConstructorTest { //这个方法用于实现对object对象的拷贝操作 public Object copy (Object object) throws Exception { /* Class<?> classType =
object.getClass(); //可以用于各种构造函数 Constructor cons =
classType.getConstructor(new Class[]{String.class , int.class}); Object obj = cons.newInstance(new
Object[]{"Jack", 30}); //以上两行相当于下面的一行,但是下面这种用法,只能用于无参的构造函数。 //Object obj1 =
classType.newInstance(); System.out.println(obj);*/ Class<?> classType =
object.getClass(); Object objCopy =
classType.getConstructor(new Class[]{}).newInstance(new Object[]{}); Field[] fields =
classType.getDeclaredFields(); for(Field field : fields) { String name = field.getName(); String firstLetter =
name.substring(0,1).toUpperCase(); String getMethodName = "get" + firstLetter + name.substring(1); String setMethodName = "set" + firstLetter + name.substring(1); Method getMethod =
classType.getMethod(getMethodName,new Class[]{}); Method setMethod = classType.getMethod(setMethodName,new
Class[]{field.getType()}); Object value =
getMethod.invoke(object, new Object[]{}); setMethod.invoke(objCopy, new
Object[]{value}); } return objCopy; } public static void main(String[] args) throws Exception { Customer customer = new Customer("Jack",30); customer.setId(1L); ConstructorTest test = new
ConstructorTest(); Customer customer2 =
(Customer)test.copy(customer); System.out.println(customer2.getId()+ "," +
customer2.getName() + "," + customer2.getAge()); } } |
使用反射创建数组
public class ArrayTest2 { public static void main(String[] args) { int[] dims = new int[]{5, 10, 15}; Object array = Array.newInstance(Integer.TYPE, dims); Object arrObj = Array.get(array,
3); Class<?> classType =
arrObj.getClass().getComponentType(); System.out.println(classType); arrObj = Array.get(arrObj , 5); Array.setInt(arrObj, 10, 35); int[][][] arrCast = (int[][][])array; System.out.println(arrCast[3][5][10]); } } |
public class ArrayTest { public static void main(String[] args) throws Exception { Class<?> classType = Class.forName("java.lang.String"); Object array = Array.newInstance(classType,
10); Array.set(array, 5, "Jack"); Object val = Array.get(array,
5); System.out.println(val); } } |
使用反射调用类里的私有方法:
public class PrivateTest { public static void main(String[] args) throws Exception { Person p = new Person(); Class<?> classType =
p.getClass(); Method method = classType.getDeclaredMethod("sayHello" ,new Class[]{String.class}); method.setAccessible(true);//压制java的类型检查 Object val = method.invoke(p, new Object[]{"Alens"}); System.out.println(val); } } class Person { private String sayHello(String name) { return "Hello," + name; } } |
public class PrivateTest2 { public static void main(String[] args) throws Exception { People p = new People(); Class<?> classType =
p.getClass(); Field field =
classType.getDeclaredField("name"); field.setAccessible(true); field.set(p, "Lisi"); Method method =
classType.getDeclaredMethod("getName", new Class[]{}); Object name = method.invoke(p, new Object[]{}); System.out.println(name); } } class People { private String name = "ZhangSan"; public String getName() { return this.name; } } |
注意:Integer.Type返回的是int,而Integer.class返回的是Class对象。