Java RTTI 和 反射机制
运行时,识别对象和类的信息有两种方法:
1、RTTI
2、“反射”机制
RTTI 即 Run Time Type Identification 运行时类型识别
在java中,RTTI表现在:
1、Class对象是RTTI的核心,每个类都有一个Class对象
2、instanceof 关键字,用于检查对象是不是某个特定类型的实例
3、强制类型转换
RTTI示例:
1 public class RTTITest { 2 3 public static void main(String[] args) { 4 Number n = 123L; 5 6 //c1 c2 c3都是java.lang.Class类的对象 7 Class<? extends Number> c1 = n.getClass();
8 Class<Number> c2=Number. class; 9 Class<Long> c3=Long. class; 10 11 System. out.println(c1.getName()); 12 System. out.println(c2.getName()); 13 System. out.println(c3.getName()); 14 15 //== 和 equals()是等价的 16 System. out.println((c1==c2)+" " +(c1.equals(c2))); 17 System. out.println(c1.equals(c3)); 18 19 //instanceof 关键字和Class.isInstance等价的 20 //指“你是这个类吗?或者 你是这个类的派生类吗?” 21 System. out.println(n instanceof Number); 22 System. out.println(Number.class.isInstance(n)); 23 System. out.println(n instanceof Long); 24 System. out.println(Long.class.isInstance(n)); 25 } 26 }
java.lang.Long ---- n.getClass().返回对象n运行时的Class对象,所以是Long.class,而不是Number.class
java.lang.Number
java.lang.Long
false false
true
true
true
true
true
Java语言的反射机制
使java具有动态语言的特性:动态获取类的信息、动态调用类的方法
Java反射机制提供一下功能:
1、运行时判断任意一个对象所属的类
2、运行时构造任意一个类的对象
3、运行时判读任意一个类所具有的成员变量和方法(通过反射甚至可以调用private方法)
4、运行时调用任意一个对象的方法
Java反射机制相关的API简介(位于java.lang.reflect)
Class类:代表一个类
Field类:代表类的成员变量
Method类:代表类的方法
Constructor类:代表类的构造方法
1 import java.lang.reflect.Field; 2 import java.lang.reflect.Method; 3 import java.lang.reflect.Modifier; 4 5 6 class Person{ 7 private final String name; 8 private int age = 20; 9 private String sex; 10 11 public Person(String name) { 12 this.name = name; 13 } 14 public void sayHello(String name, int age) { 15 System.out.println(name + " " + age); 16 } 17 18 public int getAge() { 19 return age; 20 } 21 public void setAge(int age) { 22 this.age = age; 23 } 24 public String getSex() { 25 return sex; 26 } 27 public void setSex(String sex) { 28 this.sex = sex; 29 } 30 public String getName() { 31 return name; 32 } 33 } 34 35 public class WatchClassInfo { 36 37 public static void main(String[] args) throws Exception { 38 Person person = new Person("Shao"); 39 person.setSex("man"); 40 Class<?> c = person.getClass();//获得运行时对象的类对象 41 Class<?> superClass=person.getClass().getSuperclass();//获得运行时对象的基类类对象 42 43 System.out.println("class loader : "+c.getClassLoader()); 44 System.out.println("class name : "+c.getName()); 45 System.out.println("super class name "+superClass.getName()); 46 47 48 System.out.println("-----------查看类中声明的数据成员,及其值-----------"); 49 Field[] fields=c.getDeclaredFields();//获得类的数据成员信息 50 for (int i = 0; i < fields.length; i++) { 51 Field field=fields[i]; 52 System.out.print(field.getType().getSimpleName()+" "+field.getName()); 53 54 String fieldName=field.getName(); 55 String upper=fieldName.substring(0, 1).toUpperCase(); 56 String getName="get"+upper+fieldName.substring(1); 57 Method getMethod=c.getMethod(getName, new Class[]{}); 58 59 Object fieldValue=getMethod.invoke(person,new Object[]{});//在person对象上调用getter方法 60 System.out.println(" = "+fieldValue); 61 } 62 63 64 System.out.println("-----------查看类中声明的方法-------------------"); 65 Method method[] = c.getDeclaredMethods();//获得类的方法信息 66 for (int i = 0; i < method.length; ++i) { 67 Class<?> returnType = method[i].getReturnType(); 68 Class<?> para[] = method[i].getParameterTypes(); 69 int temp = method[i].getModifiers(); 70 System.out.print(Modifier.toString(temp) + " "+returnType.getName() + " "+method[i].getName() + " "+"("); 71 72 for (int j = 0; j < para.length; ++j) { 73 System.out.print(para[j].getName() + " " + "arg" + j); 74 if (j < para.length - 1) { 75 System.out.print(","); 76 } 77 } 78 System.out.println(")"); 79 } 80 } 81 82 }
输出:
class loader : sun.misc.Launcher$AppClassLoader@addbf1
class name : edu.shao.typeinfo.reflect.Person
super class name java.lang.Object
-----------查看类中声明的数据成员,及其值-----------
String name = Shao
int age = 20
String sex = man
-----------查看类中声明的方法-------------------
public void setSex (java.lang.String arg0)
public void sayHello (java.lang.String arg0,int arg1)
public int getAge ()
public void setAge (int arg0)
public java.lang.String getSex ()
public java.lang.String getName ()
RTTI和反射之间真正的区别在于:
1、对于RTTI来说,编辑器在编译时打开或检查.class文件。换句话说,我们可以用“普通”方法调用对象的所有方法。
2、对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。