有九种预定义的 Class 对象,表示八个基本类型和 void。这些类对象由 Java 虚拟机创建,与其表示的基本类型同名,即 boolean、byte、char、short、int、long、float 和 double。
数组类型的Class实例对象
Class.isArray()
总之,只要是在源程序中出现的类型,都有各自的Class实例对象,例如,int[],void…
Constructor类
Constructor 提供关于类的单个构造方法的信息以及对它的访问权限。
得到某个类所有的构造方法:
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
得到某个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructor(StringBuffer.class);
创建实例对象
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
Class.newInstance()方法:
String obj = (String)Class.forName("java.lang.String").newInstance();
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象.
该方法内部的具体代码是怎么写的呢?用到了缓存机制来保存默认构造方法的实例对象.
Field类
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限。反射的字段可能是一个类(静态)字段或实例字段。
重要方法:
Object get(Object obj)
返回指定对象上此 Field 表示的字段的值。
void set(Object obj, Object value)
将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
练习:
将任意一个对象中的所有String类型的成员变量所对应的字符串内容中的”b” 改成”a”。
private static void changeStringValue(Object obj)throws Exception{
Field[] fields = obj.getClass().getFields();
for(Field field:fields){
if(field.getType() == String.class){
String oldValue = (String)field.get(obj);
String newValue = oldValue.replace('b','a');
field.set(obj,newValue);
}
}
Method类
Method 提供关于类或接口上单独某个方法(以及如何访问该方法)的信息。所反映的方法可能是类方法或实例方法(包括抽象方法)。
Method 允许在匹配要调用的实参与底层方法的形参时进行扩展转换;但如果要进行收缩转换,则会抛出 IllegalArgumentException。
得到类中的某一个方法:
Method chatAtMethod = Class.forName("java.lang.String").getMethod("chatAt",int.class);
调用方法:
通常方式:str.chatAt(1)
反射方式:chatAtMethod.invoke(str,1);
如果传递给Method对象的invoke()方法的第一个参数为null,说明该Method对象对应的是一个静态方法
JDK1.4和JDK1.5的invoke方法的区别:
- JDK1.5: public Object invoke(Object obj,Object… args)
- JDK1.4: public Object invoke(Object obj,Object[] args),按1.4的语法,需要将一个数组作为参数传递给invoke方法时, 数组中的每个元素分别对应被调用方法中的一个参数,所以,调用chatAt方法的代码也可以用JDK1.4改写为chatAtMethod.invoke(“str”,new Object[]{1})形式.
Object invoke(Object obj, Object... args)
对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。
用反射方式执行某个类中的main方法
String startingClassName = args[0];
Method mainMethod = Class.forName(startingClassName).getMethod("main",String[].class);
mainMethod.invoke(null,(Object)new String[]{"111","222","333"});
调用时传递数组参数出现问题的解决方法:
- mainMethod.invoke(null,new Object[]{new String[]{“xxx”}});
- mainMethod.invoke(null,(Object)new String[]{“xxx”});编译器会做特殊处理,编译时不把参数当作数组看待,也就不会数组打散成若干个参数了.
Array类
Array 类提供了动态创建和访问 Java 数组的方法。
Array 允许在执行 get 或 set 操作期间进行扩展转换,但如果发生收缩转换,则抛出 IllegalArgumentException。
static Object get(Object array, int index)
返回指定数组对象中索引组件的值。
static int getLength(Object array)
以 int 形式返回指定数组对象的长度。
static void set(Object array, int index, Object value)
将指定数组对象中索引组件的值设置为指定的新值。
练习:
打印数组中各个元素,或者打印一个元素
private static void printObject(Object obj){
Class clazz = obj.getClass();
if(clazz.isArray()){
int len = Array.getLength(obj);
for(int i=0;i<len;i++){
System.out.println(Array.get(obj,i));
}
}else{
System.out.println(obj);
}
}