反射的基石--Class类
1.什么是Class。Java程序中的各个Java类属于同一类事物,描述这类事物的Java类名就是Class。
Java类用于描述一类事物的共性,该类事物有什么属性,没有什么属性,至于这个属性的值是什么,则由这个类的实例
对象来确定,不同的实例对象有什么不同的属性值,
Class cls
Class的实例对象代表字节码。
什么是字节码?
某个类编译后保存在硬盘上的二进制代码。
当我们用到某个类的时候,首先要把该类的字节码加载到内存中,再创建该类的对象。
2.如何得到各个字节码对应的实例对象(Class类型)
● 类名.class,例如, System.class;
● 对象.getClass(), 例如,new Date().getClass();
● Class.forName("类名"), 例如, Class.forName("java.util.Date");
3.九个预定义Class实例对象
● 每一个基本类型都对应一个Class对象,void也有对应的Class对象。
● 参看Clas.isPrimitive方法帮助
ps:int.class == Integer.TYPE
4.数组类型的Class实例对象
● Class.isArray()
总之,只要在源程序中出现的类型,都有各自的Class实例对象,例如,int[], void...
反射
什么叫反射:发射就是把Java类中的各种成分映射成相应的java类。(传智学员 冯伟立总结)
Constructor类
Constructor类代表某个类中的一个构造方法。
● 得到某个类的所有构造方法:
Constructor[] constructors = Class.forName("java.lang.String").getConstructors();
● 得到一个构造方法:
Constructor constructor = Class.forName("java.lang.String").getConstructors(StringBuffer.class);
● 创建实例对象:
通常方式:String str = new String(new StringBuffer("abc"));
反射方式:String str = (String)constructor.newInstance(new StringBuffer("abc"));
● Class.newInstance()方法:
该方法内部先得到默认的构造方法,然后用该构造方法创建实例对象。
该方法内部的具体代码,用到了缓存机制来保存默认构造方法的实例对象。
Field类
Field类代表某个类中的一个成员变量。
Ps:字节码比较用 == ,更准确,因为字节码只有一份。
示例:
public static void main(String[] args) throws NoSuchFieldException, Exception {
ReflectPoint rp = new ReflectPoint(6,7);
// 取得私有成员变量
Field fieldx = rp.getClass().getDeclaredField("x");
// 取得公有成员变量
Field fieldy = rp.getClass().getField("y");
// 获取私有变量的值
fieldx.setAccessible(true);
int vlauex = fieldx.getInt(rp);
// 获取公有变量的值
int valuey = fieldy.getInt(rp);
System.out.println(vlauex);
System.out.println(fieldy);
}
Method类
Method类某个类中的一个方法。
Ps:如果传递给Method对象的invoke()方法的第一个参数为null,说明给对象是一个静态方法。
用反射方式执行某个类中的main方法
通过反射方式来调用这个main方法时,按jdk1.5的语法,整个数组是一个参数,而按jdk1.4的语法,数组中的每个元素都对应一个
参数,当把一个字符串数组作为参数传递给invoke方法时,javac会按照jdk1.4的语法进行处理,即,把数组打散成若干个单独的
参数。所以,在给main方法传递参数时,不用使用代码 mainMethod.invoke(null, new String[] {"xxx","xxx",...}),否则会出现
参数类型不对问题。
解决办法:
mainMethod.invoke(null, new Object() {new String[] {"xxx","xxx",...}});
mainMethod.invoke(null, (Object)new String[] {"xxx","xxx",...})
示例:
public static void main(String[] args) throws NoSuchFieldException, Exception {
ReflectPoint rp = new ReflectPoint(6,7);
Method methodMain = rp.getClass().getMethod("main", String[].class);
methodMain.invoke(null, (Object)new String[] {"a", "b", "c"});
}
数组与Object的关系及其反射类型
数组的反射
具有相同维数和元素类型的数组属于同一个类型,即,具有相同的Class实例对象。
基本类型的一维数组可以被当做Object类型使用,不能被当做Object[]类型使用,非基本类型的一维数组,既可以当做Object类型
使用,又可以当做Object[]类型使用。
反射的作用-->实现框架功能
package it.practise.com.reflect;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Properties;
public class ReflectTest {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
InputStream is = new FileInputStream("config.properties");
Properties pros = new Properties();
pros.load(is);
is.close();
String className = pros.getProperty("className");
Collection collections = (Collection)Class.forName(className).newInstance();
ReflectPoint pt1 = new ReflectPoint(3,3);
ReflectPoint pt2 = new ReflectPoint(5,5);
ReflectPoint pt3 = new ReflectPoint(3,3);
collections.add(pt1);
collections.add(pt2);
collections.add(pt3);
collections.add(pt1);
System.out.println(collections.size());
}
}
ReflectPoint类
<pre name="code" class="java">package it.practise.com.reflect;
import java.util.Arrays;
public class ReflectPoint {
private int x = 1;
public int y = 2;
ReflectPoint(int x, int y) {
this.x = x;
this.y = y;
}
public int sum() {
return x + y;
}
public static void main(String[] args) {
System.out.println(Arrays.asList(args));
}
}
config.properties文件内容
className=java.util.ArrayList