《Think in Java》类型信息 – 学习笔记

Class对象

Class对象是一种特殊的对象,它包含了与类有关的信息。Class对象用来创建类的所有的“常规”对象。Java使用Class对象来执行RTTI(包括类型转换操作)。
每当编写并编译一个新类,就会产生一个Class对象(或者说被保存在一个同名的.class文件中)。

Class对象的引用可以通过Class.forName()或普通对象的getClass()方法来获取,或类名加上.class来获得。其中,getClass()方法属于根类Object的一部分。”.class”称为类字面常量,他在编译时就会受到检查,所以更安全,也更高效。

差别:“.class”不会引起类的初始化,而Class.forName()方法会立即就进行初始化。

Class对象包含很多有用的方法,能够了解一个类型的所有信息,比如:

  1. getName():产生全限定的类名
  2. getSimpleName():产生不含包名的类名
  3. getCanonicalName():产生全限定的类名
  4. isInterface():判定这个Class对象是否表示某个接口
  5. getSuperclass():查询直接基类```

如果调用Class对象的newInstance()方法来实例化一个类,则这个类必须带有默认构造器。

为了使用类而做的准备工作实际包含3个步骤:

  1. 加载。这是由类加载器执行的。该步骤查找字节码并从这些字节码中创建一个Class对象。
  2. 链接。在链接阶段将验证类中的字节码,为静态域分配存储空间,并且如果必要的话,将解析这个类创建的对其他类的所有引用。
  3. 初始化。如果该类具有超类,则对其初始化,执行静态初始化器和静态初始化块。

反射:运行时的类信息

RTTI和反射之间真正的区别只在于,对RTTI来说,编译器在编译时打开和检查.class文件(即我们可以用“普通”方式调用对象的所有方法)。而对于反射机制来说,.class文件在编译时是不可获取的,所以是在运行时打开和检查.class文件。

Class类与java.lang.reflect类库一起对反射的概念进行了支撑,该类库包含了Field、Method以及Constructor类(每个类都实现了Member接口)。这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员。这样就可以使用Constructor创建新的对象,用get()和set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。另外,还可以调用getField()、getMethods()和getConstructors()等很便利的方法,以返回表示字段、方法以及构造器的对象的数组。这样,匿名对象的类信息就能在运行时被完全确定下来,而在编译时不需要知道任何事情。

用如下代码来测试反射机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectTest {

public static void main(String[] args) {
try {
Class<?> appleClass = Class.forName("classinfo.Apple");
System.out.println("===Methods:===\n");
for( Method method : appleClass.getMethods()){
System.out.println(method.toString());
}

System.out.println("===Constructors:===\n");
for( Constructor<?> cons : appleClass.getConstructors()){
System.out.println(cons.toString());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}

}

}

class Apple {
private int weight;
private String color;

public Apple() {
super();
}

public Apple(int weight, String color) {
super();
this.weight = weight;
this.color = color;
}

public int incWeight(){
return ++weight;
}

public int decWeight(){
return --weight;
}
}

运行结果为:

===Methods:===
public int classinfo.Apple.incWeight()
public int classinfo.Apple.decWeight()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()

===Constructors:===
public classinfo.Apple()
public classinfo.Apple(int,java.lang.String)

文章目录
  1. 1. Class对象
  2. 2. 反射:运行时的类信息