首先需要获取类型类,一般获取类型类有三种方式
- 从类名获得:MyClass.class即可,适用于知道类名
- 从对象获得:myClass.getClass(),适用于有对象句柄
- 偷来的:Class.forName(“com.crimson.MyClass”)需要类名和包名,不常用
这里选了第一种,假设获取的对象为a。
然后是获取该类型的构造器,方法和字段。
全都依靠以get开头的各种方法。
根据返回对象不同有constructor、field、method三种,意思是构造器、字段和方法。根据访问权限不同有公开的和公开+私有,加上Declared获取的就是公开+私有。
如getDeclaredMethods获取所有方法、getMethods仅获取公开方法,getFields仅获取公开的字段。返回对象的用对应的数组装起来就可以了,在代码里第一段里有演示。如Method methods[]=a.getDeclaredMethods()。
private的可以访问前,先setAccessible(true),把访问权限强制打开,访问完记得再关闭就可以了。
获取指定名字的字段方法和构造器,字段和方法把名字作为参数,如getDeclaredMethod(“setId”),注意结尾是method没有s,因为只获取单个方法,也不需要用数组装了。直接Method m=getMethod(“myMethod”)。
对于获取指定的构造器,get方法里面填想获取构造器的参数的class,无参的就不填。
如果你想获取MyClass(int,int)的构造器,就getDeclaredConstructor(int.class,int.class)就可以了
同样的,获取的是单个构造器,注意结尾没有s。
对于已经获取到的构造器例如c,可以使用它的newInstance方法获取它制造的新对象,如c.newInstance(100,200)
对于已经获取到的字段对象,可以读取出来,使用get(对象)或者getInt()之类用于基本数据类型,还可以用set(对象,值)设值。
对于已经获取的方法,可以用invoke(对象,参数)调用该方法。具体流程参见下面代码。
代码如下
package com.crimson.master;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** 分析反射 */
public class MyReflection
{
public MyReflection(int n)
{
this.a=n;
}
public int getA()
{
return a;
}
public void setA(int a)
{
this.a = a;
}
private void setB(int n)
{
this.b=n;
}
private int a=0;
public int b=0;
public static void main(String[] args)
{
MyReflection myReflection=new MyReflection(-1);
Class<?> myReflectionClass=myReflection.getClass();
//获取所有构造器并打印
Constructor<?> constructors[]=myReflectionClass.getDeclaredConstructors();
System.out.println(constructors);
//获取所有方法与字段
Method methods[]=myReflectionClass.getDeclaredMethods();
Field fields[]=myReflectionClass.getDeclaredFields();
//打印方法与字段名
List<Method> mlist=new ArrayList<Method>(Arrays.asList(methods));
mlist.stream().forEach(System.out::println);
List<Field> mfield=new ArrayList<Field>(Arrays.asList(fields));
mfield.stream().forEach(System.out::println);
try
{
//测试从构造器获取对象
Constructor<?> intConstructor=myReflectionClass.getDeclaredConstructor(int.class);
System.out.println(intConstructor);
MyReflection newIns=(MyReflection)intConstructor.newInstance(900);
System.out.println(newIns.getA());
//测试字段,访问private字段
Field a=myReflectionClass.getDeclaredField("a");
a.setAccessible(true);//开权限
System.out.println(a.getInt(myReflection));
a.set(myReflection,100);//反射所提供的set方法
a.setAccessible(false);//关权限
System.out.println(myReflection.getA());
//测试方法
Method seta=myReflectionClass.getDeclaredMethod("setA",int.class);
seta.invoke(myReflection,200);//调用方法
System.out.println(myReflection.getA());
} catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | InstantiationException e)
{
e.printStackTrace();
}
}
}