Object obj = new Object();
Class cl = obj.getClass();
String className = "java.util.Random";//包的名字也作为类名一部分
Class cl = Class.forName(className);
Class cl1 = Random.class;
Class cl2 = int.class;
if(e.getClass() == Random.class)...
Object m = cl.newInstance();//如果没有默认构造器,将会抛出异常
Object m = cl.newInstance(a,b,c);
java.lang.reflect包中有三个类Field、Method和Constructor分别描述类的域、方法和构造器。
在Class对象中,可以调用以下方法获取上述结构
Field[] getFields();//获取该类以及父类(如果有)的公开域
Field[] getDeclaredFields();//获取该类所有域
Method[] getMethods();//获取该类以及父类(如果有)的公开方法
Method[] getDeclaredMethods();//获取该类所有方法
Constructor[] getConstructors();//获取公开构造器
Constructor[] getDeclaredConstructors();//获取该类所有构造器
Class getDeclaringClass()
返回Field.class,Method.class或Constructor.class,即返回描述类中定义的构造器,方法或域的Class对象.
Class[] getExceptionTypes()
仅在Constructor和Method类中,返回一个描述方法抛出的异常类型的Class数组
int getModifiers()
返回一个用于描述构造器,方法或域的修饰符的int值,使用Modifier类中的这个方法可以分析这个返回值。
String getName()
返回一个用于描述构造器,方法或域名的字符串
Class[] getParameterTypes()
仅在Constructor和Method类中,返回一个用于描述参数类型的Class对象数组
Class getReturnedType()
仅在Method类中,返回一个用于描述返回类型的Class对象。
static String toString(int modifiers);
static boolean isAbstract(int modifiers);
static boolean isFinal(int modifiers);
...
这些方法可以用来检测方法名中对应的修饰符在modifier值中的情况。
void setAccessible(boolean flag)
为反射对象设置可访问标志,true表示屏蔽Java语言的访问检查,即便是私有属性也可以被查询和设置。
boolean isAccessible()
返回反射对象的可访问标志的值
static void setAccessible(AccessibleObject[] array, boolean flag)
设置对象数组可访问标志的快捷方式
Field getField(String name);
Field[] getFields();//返回指定名称的公有域,或包含可检查的域的数组
Field getDeclaredField(String name);
Field[] getDeclaredFields();//获取类中声明的给定名称的域,或者包含声明的全部域的数组
Object get(Object obj);//返回obj对象中用Field对象表示的域的值
void set(Object obj, Object newValue);//用一个新值设置Obj对象中Field对象表示的域
例如现在有一个男孩,需要更改其名字
Boy boy = new Boy("张三");
Class cl = boy.getClass();
Field f = cl.getDeclaredField("name");//注意用Declared
f.setAccessible(true);//设置屏蔽Java的访问检查
f.set(boy,"李四");//更改boy对象中与变量f(一个cl中叫做name的域)对应的值
理解一段代码,用于数组扩展
public static Object goodCopyOf(Object a, int newLength){
Class cl = a.getClass();
if(!cl.isArray()) return null;
Class componentType = cl.getComponentType();
int length = Array.getLength(a);
Object newArray = Array.newInstance(componentType,newLength);
System.arraycopy(a,0,newArray,0,Math.min(length,newLength));
return newArray;
}
传入的原数组a用的是Object类型,而不用Object[]类型,因为int[]不能转为Object[]类型。
首先判断a是不是Array类型,其次再通过getComponentType获取数组元素类型,如果cl不是Array的类的话,将会返回null。
之所以要通过元素类型来创建一个例如Employee[]的新数组,而不是直接创建一个Object[]的新数组,是因为Object[]无法直接转成Employee[],这会带来困扰。
static Object get(Object array,int index);
static xxx getXxx(Object array,int index);//xxx为boolean,byte,char等,用于返回存储在给定位置上的给定数组的内容
static void set(Object array,int index,Object newValue);
static setXxx(Object array,int index, xxx newValue);//xxx为boolean,byte,char等,用于将一个新的值存储到给定位置上的给定数组中
static int getLength(Object array);//返回数组长度
static Object newInstance(Class componentType, int length);
static Object newInstance(Class componentType, int[] lengths);
//返回一个具有给定类型,给定维度的数组
Method类中有一个invoke方法,它允许调用包装在当前Method对象中的方法。invoke的方法签名是:
Object invoke(Object obj, Object... args);
第一个是隐式参数,其余都是显式参数。(隐式参数:方法的调用者;显式参数:在方法参数列表中声明的参数)
如果是静态方法,第一个参数obj设置为null。在使用包装器传递基本类型的值的时候,基本类型的返回值必须是未包装的。
下面是示例:
public class Boy{
private String name;
public String getName(){return name;}
private void setName(String newName){this.name = newName;}
private static void sayHello(){
System.out.println("hello");
}
}
首先通过反射设置新名字
Boy boy = new Boy("张三");
Class cl = boy.getClass();
Method m1 = cl.getDeclaredMethod("setName",String.class);
m1.setAccessible(true);//method也需要屏蔽Java的访问检查
m1.invoke(boy,"李四");//调用者为boy对象,调用时需要的参数为新的名字"李四"
Method m2 = cl.getDeclaredMethod("sayHello");
m2.setAccessible(true);
m2.invoke(null);//静态方法,隐式参数为null(调用者设置为null)