# 类文字作为运行时类型标记

> 原文： [https://docs.oracle.com/javase/tutorial/extra/generics/literals.html](https://docs.oracle.com/javase/tutorial/extra/generics/literals.html)

JDK 5.0 中的一个变化是类`java.lang.Class`是通用的。这是一个有趣的例子，它将泛化用于容器类以外的东西。

既然`Class`有一个类型参数`T`，你可能会问，`T`代表什么？它代表`Class`对象所代表的类型。

例如，`String.class`的类型为`Class&lt;String&gt;`，`Serializable.class`的类型为`Class&lt;Serializable&gt;`。这可用于改善反射代码的类型安全性。

特别是，由于`Class`中的`newInstance()`方法现在返回`T`，因此在反射创建对象时可以获得更精确的类型。

例如，假设您需要编写一个执行数据库查询的实用程序方法，以 SQL 字符串形式给出，并返回数据库中与该查询匹配的对象集合。

一种方法是显式传入工厂对象，编写如下代码：

```
interface Factory<T> { T make();} 

public <T> Collection<T> select(Factory<T> factory, String statement) { 
    Collection<T> result = new ArrayList<T>(); 

    /* Run sql query using jdbc */  
    for (/* Iterate over jdbc results. */) { 
        T item = factory.make();
        /* Use reflection and set all of item's 
         * fields from sql results. 
         */ 
        result.add(item); 
    } 
    return result; 
}

```

您可以将其称为

```
select(new Factory<EmpInfo>(){ 
    public EmpInfo make() {
        return new EmpInfo();
    }}, "selection string");

```

或者您可以声明一个类`EmpInfoFactory`来支持`Factory`接口

```
class EmpInfoFactory implements Factory<EmpInfo> {
    ...
    public EmpInfo make() { 
        return new EmpInfo();
    }
}

```

并称之为

```
select(getMyEmpInfoFactory(), "selection string");

```

该解决方案的缺点是它需要：

*   在调用站点使用详细的匿名工厂类，或
*   为每个使用的类型声明一个工厂类，并在调用站点传递工厂实例，这有点不自然。

将类文字用作工厂对象是很自然的，然后可以通过反射使用它。今天（没有泛型）代码可能写成：

```
Collection emps = sqlUtility.select(EmpInfo.class, "select * from emps");
...
public static Collection select(Class c, String sqlStatement) { 
    Collection result = new ArrayList();
    /* Run sql query using jdbc. */
    for (/* Iterate over jdbc results. */ ) { 
        Object item = c.newInstance(); 
        /* Use reflection and set all of item's
         * fields from sql results. 
         */  
        result.add(item); 
    } 
    return result; 
}

```

但是，这不会给我们提供我们想要的精确类型的集合。既然`Class`是通用的，我们可以编写以下内容：

```
Collection<EmpInfo> 
    emps = sqlUtility.select(EmpInfo.class, "select * from emps");
...
public static <T> Collection<T> select(Class<T> c, String sqlStatement) { 
    Collection<T> result = new ArrayList<T>();
    /* Run sql query using jdbc. */
    for (/* Iterate over jdbc results. */ ) { 
        T item = c.newInstance(); 
        /* Use reflection and set all of item's
         * fields from sql results. 
         */  
        result.add(item);
    } 
    return result; 
} 

```

上面的代码以类型安全的方式为我们提供了精确的集合类型。

这种使用类文字作为运行时类型标记的技术是一个非常有用的技巧。例如，这是一种习惯用法，广泛用于操作注释的新 API 中。