第14章 类型信息

14.2 Class对象

Class类:java.lang.Class 一个继承自java.lang.Object的模板类,RTTI的核心。每一个类都有一个Class类的对象,比如一个Teacher类,相应的就有一个Teacher的Class对象(程序启动前保存在Teacher.class文件中)。

所有的类都是在对其第一次使用时,动态加载到JVM中的。Java程序在它开始运行前并非被完全加载,其各个部分是在必须时才加载的。

比如对于一个Teacher类,类加载器首先检查Tearcher的Class对象是否已经加载。如果尚未加载,默认的类加载器就会根据类名查找.class文件(Tearcher.class)。一但Tearcher的Class对象被载入内存,他就被用来创建这个类的所有对象。

有两个方法可以获得某一个类的Class对象:

  1. Class.forName()
  2. Object.getClass()
  3. 类字面常量。这种形式与前两者有所不同,在于并不会初始化该Class对象。初始化被延迟到了对静态方法或者非常数静态域的首次引用时。
 1 import static java.lang.System.out;
 2 class Teacher {
 3   Teacher(String name){this.name = name;}
 4   public String getName(){return name;}
 5   private String name = "";
 6 }
 7 
 8 public class Test {
 9   public static void main(String args[]){
10       try {
11           Class teacherClass = Class.forName("Teacher");
12           out.println(teacherClass);
13           out.println(teacherClass.getCanonicalName());
14           out.println(teacherClass.getConstructors());
15           out.println(teacherClass.isAnnotation());
16           out.println(teacherClass.getClassLoader());
17           out.println(teacherClass.getDeclaredFields()[0]);
18           out.println(teacherClass.getDeclaredMethods()[0]);
19           
20           Teacher t = new Teacher("Peter");
21           out.println(t.getClass());
22           
23           Class teacherClass2 = Teacher.class;
24           out.println(teacherClass2);
25       }
26       catch (Exception e) {
27           e.printStackTrace();
28       }
29   }
30 }/*Output:
31 class Teacher
32 Teacher
33 [Ljava.lang.reflect.Constructor;@14318bb
34 false
35 sun.misc.Launcher$AppClassLoader@addbf1
36 private java.lang.String Teacher.name
37 public java.lang.String Teacher.getName()
38 class Teacher
39 class Teacher
40 */

 泛化的Class引用,下面这段代码初次读的时候没搞明白什么意思。

 1 import java.util.*;
 2 class CountedInteger{
 3   private static long counter;
 4   private final long id = counter++;
 5   public String toString() {return Long.toString(id);}
 6 }
 7 
 8 public class FilledList<T> {
 9   private Class<T> type;
10   public FilledList(Class<T> type){this.type=type;}
11   public List<T> create(int nElements){
12     List<T> l = new ArrayList<T>();
13     try{
14       for(int i = 0; i < nElements; ++i)
15         l.add(type.newInstance());
16     }
17     catch(Exception e){
18       throw new RuntimeException(e);
19     }
20     return l;
21   }
22   public static void main(String args[]){
23     FilledList<CountedInteger> fl = new FilledList<CountedInteger>(CountedInteger.class);
24     System.out.println(fl.create(15));
25   }
26 }/*
27 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
28 */

 注意:如果想要用Class.newIntance()方法的话,那么这个Class必须有一个默认构造器。

14.3 类型转换前先做检查

Java的三种RTTI形式:

1. 传统的类型转换,如(DeriveType)baseTypeObject;由RTTI确保了类型转换的正确性,如果执行一个错误的类型转换,就会抛出一个ClassCastException异常。

2. Class对象。(如前面介绍的)

3. instanceof

14.7 动态代理

http://www.techavalanche.com/2011/08/24/understanding-java-dynamic-proxy/

14.9 接口与类型信息

在反射面前,一切信息都无法隐藏。

java.lang.reflect.AccessibleObject接口定义了 setAccessible()方法可以修改访问权限。Constructor,Field和Method类都实现了这个接口。

posted on 2013-05-03 23:58  peter9606  阅读(161)  评论(0编辑  收藏  举报

导航