[译] 泛型 8.类字面量作为运行时类型标记

本文探讨了Java 5.0中引入的泛型特性,特别是如何利用类字面量作为运行时类型标记,增强反射代码的类型安全性。通过示例展示了在数据库查询中使用类字面量创建类型安全的对象集合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<< 细则 · 目录 · 通配符的更多用法 >>

                                                                                  

类字面量作为运行时类型标记 (Class Literals as Runtime-Type Tokens)

JDK5.0中的一个变化是类java.lang.Class是泛型类。这是除容器类之外使用泛型的类,是一个有趣的例子。

既然Class有一个类型参数T,您很可能会问,T代表什么?它表示Class对象所表示的类型。

比如说,String.class的类型是Class<String>,Serializable.class的类型是Class<Serializable>。这可以用于提高反射代码的类型安全性。

特别是,由于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>(); 

    /* 使用jdbc执行sql进行查询 */  
    for (/* 遍历jdbc查询的结果 */) { 
        T item = factory.make();
        /*  对查询的结果
         *  使用反射设置item的属性
         */ 
        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();
    /* 使用jdbc执行sql进行查询 */  
    for (/* 遍历jdbc查询的结果 */) { 
        Object item = c.newInstance(); 
        /*  对查询的结果
         *  使用反射设置item的属性
         */  
        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>();
    /* 使用jdbc执行sql进行查询 */  
    for (/* 遍历jdbc查询的结果 */) { 
        T item = c.newInstance(); 
        /*  对查询的结果
         *  使用反射设置item的属性
         */   
        result.add(item);
    }
    return result; 
} 

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

这种使用类字面量作为运行时类型标记的技术是一个非常有用的技巧。例如,它在新的api中被广泛用于操作注释。

                                                                                  

<< 细则 · 目录 · 通配符的更多用法 >>

本文译自:https://docs.oracle.com/javase/tutorial/extra/generics/literals.html

转载于:https://my.oschina.net/tita/blog/2886699

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值