优秀的编程知识分享平台

网站首页 > 技术文章 正文

java 核心技术-12版 卷Ⅰ- 5.9.1 Class 类

nanyue 2024-09-20 21:43:53 技术文章 3 ℃

原文

5.9.1 Class 类

在程序运行期间,Java 运行时系统始终为所有对象维护一个运行时类型标识 (runtime type identification)。这个信息会跟踪每个对象所属的类。虚拟机利用运行时类型信息选择要执行的正确方法。

?不过,还可以使用一个特殊的 Java 类访问这些信息。保存这些信息的类名为 Class,这名字有些让人困惑。Object 类中的 getClass() 方法将会返回一个 Class 类型的实例。

Employee e;

//

Class cl = e.getClass();

?就像 Employee 对象描述一个特定员工的属性一样,Class 对象会描述一个特定类的属性。可能最常用的 Class 方法就是 getName。这个方法将返回类的名字。例如,下面这条语句:

System.out.println(e.getClass() + " " + e.getName());

?如果 e 是一个员工,则会输出:Employee Harry Hacker

?如果 e 是经理,则会输出: Manager Harry Hacker

?如果类在一个包里,包名也作为类名的一部分:

var generator = new Random();

Class cl = generator.getClass();

String name = cl.getName() ;// name is set to "java.util.Random";

还可以使用静态方法 forName 获得类名对应的class 对象

?

String className ="java.util.Random"

Class cl = Class.forName(className);

?如果类名保存在一个字符串中,这个字符串会在运行时变化,就可以使用这个方法。如果ClassName 是一个类名或接口名,这个方法可以正常执行。否则,forName 方法将抛出一个检查型异常 (checked exception)。无论何时使用这个方法,都应该提供一个异常处理器(exception handler)。关于如何提供异常处理器,请参见下一节。

?获得 class 类对象的第三种方法是一个很方便的快捷方式。如果T是任意的 Java 类型(或 void 关键字),T.class 将是匹配的类对象。例如:

?Class cll = Random.class; // if you import java,util.*;

?Class cl2 = int.class;

?Class cl3 = Double[].class;

请注意,class 对象实际上描述的是一个类型,这可能是类,也可能不是类。例如,int不是类,但 int.class 确实是一个 Class 类型的对象。

?注释:Class 类实际上是一个泛型类。例如,Employee.class 的类型是 Class<Employee>。我们没有深究这个问题,这是因为它会让已经很抽象的概念变得更加复杂。在大多数实际应用中,可以忽略类型参数,而使用原始的 Class 类。有关这个问题更详细的介绍请参见第8章。

?警告:鉴于历史原因,getName 方法对数组类型会返回有些奇怪的名字:Double[].class.getName() 返回“[Ljava.lang.Double;"。

int[].class.getName()返回[I" 。

?虚拟机为每个类型管理一个唯一的 Class 对象。因此,可以使用 == 运算符比较两个类对象。例如,

if(e.getClass() == Employee.class) ...

?如果e是一个Employee 实例,则这个测试将通过。与条件e instanceof Employee 不同,如果e 是某个子类 (如 Manager) 的实例,则这个测试将失败。

?如果有一个Class类型的对象,可以用它构造类的实例。调用 getConstructor 方法将得到个Constructor类型的对象,然后使用newInstance 方法来构造一个实例。例如:

var className ="java.ut1l.Random"; // or any other name of a class with// a no-arg constructor

Class cl = Class.forlame(className);
Object obj = cl.getConstructor().newInstance():

如果这个类没有无参数的构造器,则 getConstructor 方法会抛出一个异常。可以参见 5.9.7节了解如何调用其他构造器。

?注释:有一个已经废弃的 Class.toInstance 方法,它也可以利用无参数构造器构造一个实例。不过,如果构造器抛出一个检查型异常,那么这个异常将不做任何检查重新抛出。这违反了编译时异常检查的原则。与之不同,Constructor.newInstance 会把所有构造器异常包装到一个InvocationTargetException 中。

?C++注释: newInstance 方法相当于 C++ 中的虚拟构造器概念。不过,C++ 中的虚拟构造器不是一个语言特性,而是需要一个专业库支持的习惯用法。Class 类类似于 C++中的type_info类,getClass方法则等价于typeid操作符。不过,Java的Class 比 type_info功能更全面。C++的 type_info 只能给出表示类型名的一个字符串,而不能创建那个类型的新对象。

API java.lang.Class 1.0

  • static Class forName(String className) 返回一个 Class对象,表示名为 className 的类
  • Constructor getConstructor(Class... parameterTypes) JDK1.1 生成一个对象,描述有指定参数类型的构造器。参见 5.9.7 节了解如何提供参数类型的更多信息。

API java.lang.reflect.Constructor 1.1

  • ?Object newInstance(Object... params) 将 params 传递到构造器,来构造这个构造器声明类的一个新实例。参见 5.9.7 节更多地了解如何提供参数

API java,lang.Throwable 1.0

  • void printStackTrace() 将 Throwable 对象和栈轨迹打印到标准错误流。
最近发表
标签列表