1 认识 Class 类
在正常情况下,需要先有一个类的完整路径,引入之后可以按照固定的格式产生实例化对象,但是在 Java 中也允许一个实例化对象找到一个类的完整信息,那么这就是 Class 类的功能。
实例 1 代码:
package self.learn.reflect;
class X{ // 声明 Class 类
}
public class GetClassDemo01 {
public static void main(String[] args) {
X x = new X(); // 实例化 X 类对象
System.out.println(x.getClass().getName()); // 得到对象所在类
}
}
运行结果截图:
从上面代码的运行结果可以发现,通过一个对象得到了对象所在的完整的“包.类”名称,getClass()方法是 Object()类中继承而来的,此方法定义如下:
public final Class getClass()
以上的方法返回值的类型是一个 “Class” 类,实际上此类是 Java 反射的源头。所谓反射从程序的运行结果来看也很好理解,即可以通过对象反射求出类名,如图:
- 正常方式:
- 反射方式:
所有类的对象实际上都是 Class 类的实例
在 Java 中 Object 类是一切类的父类,那么所有类的对象实际上也就是 java.lang.Class 类的实例,所以所有的对象都可以转变为 java.lang.Class 类型表示。
- Class 本身表示一个类本身,通过 Class 可以完整地得到一个类中的完整结构,包括此类中的方法定义、属性定义等。如下表:
序号 | 方法 | 类型 | 描述 |
---|---|---|---|
1 | public static Class<?> forName(String className) throws ClassNotFoundException | 普通 | 传入完整的“包.类” 名称,实例化 Class 对象 |
2 | public Constructor[] getConstructors() throws SecurityException | 普通 | 得到一个类中的全部构造方法 |
3 | public Field[] getDeclareFields() throws SecurityException | 普通 | 得到一个类的父类中的全部属性 |
4 | public Field[] getFields() throws SecurityException | 普通 | 取得本类的全部属性 |
5 | public Method[] getMethods() throws SecurityException | 普通 | 取得一个类中的全部方法 |
6 | public Method getMethod(String name,Class ... parameterTypes) throws NosuchMethodException,SecurityException | 普通 | 返回一个 Method 对象,并设置一个方法中的所有参数类型 |
7 | public Class[] getInterfaces() | 普通 | 得到一个类中所实现的全部接口 |
8 | public String getName() | 普通 | 得到一个类中完整的 “包.类” 名称 |
9 | public Package getPackage() | 普通 | 得到一个类的包 |
10 | public Class getSuperClass() | 普通 | 得到一个类的父类 |
11 | public Object newInstance() throws InstantiationException,IllegalAccessException | 普通 | 根据 Class 定义的类实例化对象 |
12 | public Class<?> getComponentType() | 普通 | 返回表示数组类型的 class |
13 | public boolean isArray() | 普通 | 判断此 Class 是否是一个数组 |
在 Class 类本身没有定义任何的构造方法,所以如果要使用则首先必须通过 forName()的静态方法实例化对象。除此之外 ,也可以使用“类.class” 或 “对象.getClass()”方法实例化。
实例 2 代码:实例化 Class 类对象
package self.learn.reflect;
class X{ // 声明 Class 类
}
public class GetClassDemo01 {
public static void main(String[] args) {
Class<?> c1 = null; // 指定泛型
Class<?> c2 = null; // 指定泛型
Class<?> c3 = null; // 指定泛型
try {
c1 = Class.forName("self.learn.reflect.X"); // 最常用的形式
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
c2 = new X().getClass(); // 通过 Object 类中的方法实例化
c3 = X.class; // 通过类.class 实例化
System.out.println("类名称:"+c1.getName()); // 得到对象所在类
System.out.println("类名称:"+c2.getName()); // 得到对象所在类
System.out.println("类名称:"+c3.getName()); // 得到对象所在类
}
}
运行结果截图:
从程序的运行结果可以发现 3 种实例化 Class 对象的方式是一样的,但是使用 forName()的静态方法实例化 Class 对象是一种比较常用的方式,读者应重点掌握。
使用 forName()方法更加具备灵活性
从以上程序的 3 种使用方法可以发现,除了 forName()方法外,其他两种:类.class” 或 “对象.getClass()”都需要导入一个明确的类,这样如果一个类的操作不明确时,使用起来可能会受到一些限制。但是 forName()传入时只需要以字符串的方式传入即可,这样就让程序具备了更大的灵活性,所以这种方式是最为常见的一种方式。