Java RTTI与反射(参照Java编程思想与新浪博客)
2016-03-25 17:13
731 查看
一、Java的RTTI
RTTI(Run-Time Type Identification,通过运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,每个java里面的类都对应一个Class对象(在编写并且编译后),这个对象被保存在这个类的同名class文件里。
类加载器在类被第一次静态调用(比如一个静态方法,一个静态代码块或者new关键字调用构造器,注意contructors其实都是静态的)时会把那个对应的Class对象加载到内存中。
Class类有名的一个static方法是forName。Class.forName("classname
with packagepath");通过这个静态方法返回的一个对类的Class对象的引用,用户可以在运行时动态得到大量关于这个类的信息,包括接口,父类,方法,静态成员,甚至是像newInstance()方法这样的一个实现“虚拟构造器”的一种方式。所谓的虚拟构造器,就是声明“我不知道你的确切类型,至少在编译期不知道,但是我就是要正确的创建你的一个对象”。
比如说c是某个类的Class对象
Class superc = c.getSuperClass();
Object obj = null;
obj = c.newInstance();
毫无疑问,这个obj实际指向的对象是c的父类的一个对象。
鉴于java的单继承模式,这个父类显然是唯一确定的,尽管在编译时我完全不知道它的类名。
Java提供的另外一种更加安全的得到Class类的对象的方式是,使用类字面常量。
classname.class;
Java在RTTI中的第三种形式是最常见的。就是instanceof关键字,用法就不多说了。该关键字的调用其实就是使用了Class对象,并且返回一个布尔值。如果说instanceof和Class的比较唯一的不同,那就是instanceof如果是其子类的对象也会返回true,而Class对象比较的会是确切的那个类型。
这样得到类的Class对象可以在编译器就得到检查。
RTTI的限制?显然它在编译时必须知道一个非常重要的东西:类名(甚至是全类名)
二、Java的反射
Java中有时候在编译器为程序生成代码很久之后才会出现要处理的那个类,那么这个时候怎么才能处理这个类呢,即在编译的时候根本无法获知这个对象所属的类。答案就是利用Java的反射机制。Java的反射与RTTI的区别就在于编译时不需要知道任何事情,匿名对象的信息在运行时确定下来就可以。
例如:
[java] view
plain copy
print?
public class ShowMethods {
private static String usage=
"usage"+
"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+\\.");
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
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()));
for(Constructor cotr:ctors)
System.out.println(p.matcher(cotr.toString()));
lines=methods.length+ctors.length;
}else{
for(Method method:methods)
if(method.toString().indexOf(args[1])!=-1){
System.out.println(method.toString());
lines++;
}
}
for(Constructor ctor:ctors)
if(ctor.toString().indexOf(args[1])!=-1){
System.out.println(p.matcher(ctor.toString()).replaceAll(""));
lines++;
}
}catch(ClassNotFoundException e){
System.out.println("No such class"+e);
}
}
在这个类编译时:javac ShowMethods.java
//这个时候完全不知道
[java] view
plain copy
print?
Class<?> c=Class.forName(args[0]);
中的args[0]的内容是什么。
运行时:java ShowMethods ShowMethods
此时第二个ShowMethods为参数传递进去,即运行时才获得了类型信息。这便是反射。
原文地址:http://blog.csdn.net/sunzhenhua0608/article/details/9152569
RTTI(Run-Time Type Identification,通过运行时类型识别)的含义就是在运行时识别一个对象的类型,其对应的类是Class对象,每个java里面的类都对应一个Class对象(在编写并且编译后),这个对象被保存在这个类的同名class文件里。
类加载器在类被第一次静态调用(比如一个静态方法,一个静态代码块或者new关键字调用构造器,注意contructors其实都是静态的)时会把那个对应的Class对象加载到内存中。
Class类有名的一个static方法是forName。Class.forName("classname
with packagepath");通过这个静态方法返回的一个对类的Class对象的引用,用户可以在运行时动态得到大量关于这个类的信息,包括接口,父类,方法,静态成员,甚至是像newInstance()方法这样的一个实现“虚拟构造器”的一种方式。所谓的虚拟构造器,就是声明“我不知道你的确切类型,至少在编译期不知道,但是我就是要正确的创建你的一个对象”。
比如说c是某个类的Class对象
Class superc = c.getSuperClass();
Object obj = null;
obj = c.newInstance();
毫无疑问,这个obj实际指向的对象是c的父类的一个对象。
鉴于java的单继承模式,这个父类显然是唯一确定的,尽管在编译时我完全不知道它的类名。
Java提供的另外一种更加安全的得到Class类的对象的方式是,使用类字面常量。
classname.class;
Java在RTTI中的第三种形式是最常见的。就是instanceof关键字,用法就不多说了。该关键字的调用其实就是使用了Class对象,并且返回一个布尔值。如果说instanceof和Class的比较唯一的不同,那就是instanceof如果是其子类的对象也会返回true,而Class对象比较的会是确切的那个类型。
这样得到类的Class对象可以在编译器就得到检查。
RTTI的限制?显然它在编译时必须知道一个非常重要的东西:类名(甚至是全类名)
二、Java的反射
Java中有时候在编译器为程序生成代码很久之后才会出现要处理的那个类,那么这个时候怎么才能处理这个类呢,即在编译的时候根本无法获知这个对象所属的类。答案就是利用Java的反射机制。Java的反射与RTTI的区别就在于编译时不需要知道任何事情,匿名对象的信息在运行时确定下来就可以。
例如:
[java] view
plain copy
print?
public class ShowMethods {
private static String usage=
"usage"+
"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+\\.");
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
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()));
for(Constructor cotr:ctors)
System.out.println(p.matcher(cotr.toString()));
lines=methods.length+ctors.length;
}else{
for(Method method:methods)
if(method.toString().indexOf(args[1])!=-1){
System.out.println(method.toString());
lines++;
}
}
for(Constructor ctor:ctors)
if(ctor.toString().indexOf(args[1])!=-1){
System.out.println(p.matcher(ctor.toString()).replaceAll(""));
lines++;
}
}catch(ClassNotFoundException e){
System.out.println("No such class"+e);
}
}
在这个类编译时:javac ShowMethods.java
//这个时候完全不知道
[java] view
plain copy
print?
Class<?> c=Class.forName(args[0]);
中的args[0]的内容是什么。
运行时:java ShowMethods ShowMethods
此时第二个ShowMethods为参数传递进去,即运行时才获得了类型信息。这便是反射。
原文地址:http://blog.csdn.net/sunzhenhua0608/article/details/9152569
相关文章推荐
- JAVA基础--方法的重写overwrite 和 重载overload
- Java——文件选择框:JFileChooser
- Java中enum的用法总结
- Java存储到什么地方
- 20、在Java应用中使用Json
- Dubbo 通过Spring 配置具体启动服务
- Java中Date( )与Calendar( )简单算法
- Java编程思想重点笔记(Java开发必看)
- Java获取时间与系统时间相差8小时终极解决方案
- MyCAT报java.lang.OutOfMemoryError: Java heap space
- 数组求最大最小值
- 19、在 java web开发中怎么使用json?
- shh整合后web.xml、spring配置文件和struts.xml的内容
- Spring中AOP基本概念及配置方式
- 调用java的webservice返回null
- Java EE实现直接进入登录界面-JS页面跳转(一)
- Java中的IP对象以及本地域名解析
- Jsp El表达式使用问题javax.el.ELException: Failed to parse the expression
- Spring batch 入门学习教程(附源码)
- java中常见的3种自动任务