反射:运行时类型
如果你不知道某个对象的确切类型,RTTI可以告诉你,但有一个限制:这个类型在编译时必须已知,这样才能使用RTTI识别它,并利用这些信息做一些有用的时。换句话说,在编译时,编译器必须知道所有要通过RTTI来处理的类。
当通过反射与一个未知类型的对象打交道时,Java虚拟机只是简单地检查这个对象,看它属于哪个特定的类,就像RTTI那样。在用它做其他事情之前必须先加载那个类的Class对象。因此,那个类的.class文件对于Java虚拟机来说必须是可获得的:要么在本地机器上,要么可以通过网络获得。所以RTTI和反射之间真正的区别是:对RTTI来说,编译器在编译时打开和检查.class文件。而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。
尽管Java不是动态语言,但却有着一个非常突出的动态相关机制:Reflection.这个字的意思是"反射,印象,倒影",用在Java身上指的是我们可以在运行时加载,探知,使用编译期间完全未知的classes.换句话说,Java程序可以加载一个在运行时才得知名称的class,获取器完整的构造(但不包括methods定义),并生成器对象实体,或对其fields设置,或调用其methods这种“看透class”的能力被称为introspection(内省,内观,反省).
反射机制主要提供了以下功能:
1在运行时判断任意一个对象所属的类。
2 在运行时构造任意一个类的对象
3 在运行时构造任意一个类所具有的成员变量和方法。
4 在运行时调用一个对象和方法。
反射主要用到类在java.lang.reflect包下:
Class类,表示一个类
Field类 :代表类的成员变量即属性
Method类:代表类的方法
Constructor类: 代表类的构造方法
Array类:提供了动态创建数组,以及访问数组元素的静态方法
获取某个类的对应的Class对象的方式
使用类的.class语法
通过类的对象getClass()方法
通过Class对象的forName()方法
对于包装类可以通过.TYPE语法方式
反射机制主要强调的是运行时,还有就是只知道类名(准确的说是class文件,因为是编译好,运行时获取的),就可以得到类中的所有信息,包括private的。某种程度上可以说不安全。
简单运用:类方法提取器:
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class ShowMethods {
private static String usage="usage:\n"+"ShowMethods qualified.class.name\n"
+"To show all methods in class or :\n"+
"ShowMethods qualified.class.name word\n"
+"To search for methods involving 'word'";
private static Pattern p=Pattern.compile("\\w+\\.");
public static void main(String[] args){
if(args.length<1){
System.out.println(usage);
System.exit(0);
}
int lines=0;
try {
Class<?> c=Class.forName(args[0]);
Method[] methods=c.getMethods();
Constructor[] ctors=c.getConstructors();
if(args.length==1){
for(Method method:methods){
System.out.println(p.matcher(method.toString()).replaceAll(""));
}
for(Constructor ctor:ctors){
System.out.println(p.matcher(ctor.toString()).replaceAll(""));
}
lines=methods.length+ctors.length;
}else{
for(Method method:methods){
if(method.toString().indexOf(args[1])!=-1){
System.out.println(p.matcher(method.toString()).replaceAll(""));
lines++;
}
}
for(Constructor ctor:ctors){
if(ctor.toString().indexOf(args[1])!=-1){
System.out.println(p.matcher(ctor.toString()).replaceAll(""));
lines++;
}
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
输入的第一项是你用来加载的类的全限定名称,第二项是用来过滤该类或其继承类的方法:
你可以通过输入:java.net.Socket 或者 java.net.Socket Object来看输出结果的不同。