实例070 实例化Class类的几种方式

实例说明

Java的数据类型可以分成两类,即引用类型和原始类型。无论哪种类型的对象,Java虚拟机都会实例化不可变的java.lang.Class对象。它提供了在运行时检查对象属性的方法,这些属性包括它的成员和类型信息。更重要的是Class对象是所有反射APl的入口。本实例将演示如何获得Class对象。实例的运行效果如图7.15所示。
多学两招:Class类是泛型类,可以使用@SuppressWarnings("unchecked")忽略泛型或者使用Class<?>类型。

实现过程

(2)编写类ClassTest,在该类的main()方法中,演示各种获得Class对象的方法。关键代码如下:

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
package com.mingrisoft;

import java.util.Date;

public class ClassTest
{
@SuppressWarnings("unchecked")
public static void main(String[] args) throws ClassNotFoundException
{
System.out.println("第1种方法:Object.getClass()");
// 1.使用getClass()方式获得Class对象
Class c1 = new Date().getClass();
// 输出对象名称
System.out.println(c1.getName());
System.out.println("第2种方法:类名.class语法");
// 2.使用 类名.class 语法获得Class对象
Class c2 = boolean.class;
// 输出对象名称
System.out.println(c2.getName());
System.out.println("第3种方法:Class.forName()");
// 3.使用Class.forName()获得Class对象
Class c3 = Class.forName("java.lang.String");
// 输出对象名称
System.out.println(c3.getName());
System.out.println("第4种方法:包装类.TYPE");
// 4.使用包装类获得Class对象
Class c4 = Double.TYPE;
// 输出对象名称
System.out.println(c4.getName());
}
}

运行效果:

1
2
3
4
5
6
7
8
第1种方法:Object.getClass()
java.util.Date
第2种方法:类名.class语法
boolean
第3种方法:Class.forName()
java.lang.String
第4种方法:包装类.TYPE
double

技术要点

通常有以下4种方式可以获得Class对象。

  • Object.getClass():如果一个类的对象可用,则最简单的获得Class的方法是使用Object.getClass()。当然,这种方式只对引用类型有用。
  • .class语法:如果类型可用,但没有对象则可以在类型后加上“.class”来获得Class对象。这也是使原始类型(基本数据类型)获得Class对象的最简单的方式。
  • Class.forName("类全名"):如果知道类的全名,则可以使用静态方法Class.forName("类全名")来获得Class对象。该方法不能用在原始类型(基本数据类型)上,但是可以用在原始类型数组上。
  • 包装类的TYPE域:每个原始类型和void都有包装类,利用其TYPE域就可以获得Class对象。

实例071 查看类的声明

实例说明

通常类的声明包括常见修饰符(publicprotectedprivateabstractstaticfinalstrictfp等)、类的名称、类的泛型参数、类的继承类(实现的接口)和类的注解等。本实例将演示如何用反射获得这些信息。实例的运行效果如图7.16所示。

实现过程

编写类ClassDeclarationViewer,在main()方法中输出了与类声明相关的各个项。关键代码如下:

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.mingrisoft;

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

public class ClassDeclarationViewer
{
public static void main(String[] args) throws ClassNotFoundException
{
// 获得ArrayList类对象
Class<?> clazz = Class.forName("java.util.ArrayList");
System.out.println("类的标准名称:" + clazz.getCanonicalName());
System.out.println("类的修饰符:" + Modifier.toString(clazz.getModifiers()));

// 输出类的泛型参数
TypeVariable<?>[] typeVariables = clazz.getTypeParameters();
System.out.print("类的泛型参数:");
if (typeVariables.length != 0)
{
for (TypeVariable<?> typeVariable : typeVariables)
{
System.out.println(typeVariable + "\t");
}
} else
{
System.out.println("空");
}

// 输出类所实现的所有接口
Type[] interfaces = clazz.getGenericInterfaces();
System.out.println("类所实现的接口:");
if (interfaces.length != 0)
{
for (Type type : interfaces)
{
System.out.println("\t" + type);
}
} else
{
System.out.println("\t" + "空");
}

// 输出类的直接继承类,如果是继承自Object则返回空
Type superClass = clazz.getGenericSuperclass();
System.out.print("类的直接继承类:");
if (superClass != null)
{
System.out.println(superClass);
} else
{
System.out.println("空");
}

// 输出类的所有注释信息,有些注释信息是不能用反射获得的
Annotation[] annotations = clazz.getAnnotations();
System.out.print("类的注解:");
if (annotations.length != 0)
{
for (Annotation annotation : annotations)
{
System.out.println("\t" + annotation);
}
} else
{
System.out.println("空");
}
}
}

多学两招:通常只能通过API来查看类的定义,不过Java反射还提供了另一种方式来获得类的信息,读者也可以在程序中使用这些信息。另外,使用getInterfaces()方法也可以获得对象类的所有接口,但是不包含泛型信息。即使是getSuperclass()方法也不能获得有泛型信息的父类。

技术要点

Class类的实例表示正在运行的Java应用程序中的类和接口。枚举是一种类,注释是一种接口。每个数组属于被映射为Class对象的一个类,所有具有相同元素类型和维数的数组都共享该Class对象。基本的Java类型(booleanbytecharshortintlongfoatdouble)和关键字void也表示为Class对象。它没有公共构造方法。Class对象是在加载类时由Java虚拟机以及通过调用类加载器中的defineClass方法自动构造的。本实例使用的方法如表71所示。

方法 描述
static Class<?> forName(String className) Returns the Class object associated with the class or interface with the given string name.
TypeVariable<Class<T>>[] getTypeParameters() Returns an array of TypeVariable objects that represent the type variables declared by the generic declaration represented by this GenericDeclaration object, in declaration order.
Type[] getGenericInterfaces() Returns the s representing the interfaces directly implemented by the class or interface represented by this object.Type