关于commons-dbutils使用时一个泛型问题的疑惑?

2023-06-22 338 0

刚开始学习java,在使用commons-dbutils操作数据库,对其进一步封装的时候,有下面两种方式:


    QueryRunner queryRunner = new QueryRunner();
    // 方式1
    public <T> T queryOne(Class<T> t,String sql, Object... params) throws SQLException {
        try {
            return queryRunner.query(connection,sql,new BeanHandler<>(t),params);
        } finally {
            // 省略代码...
        }
    }
    // 方式2
    public <T> T queryOne(T t,String sql, Object... params) throws SQLException {
        try {
            // idea为什么会在(Class<? extends T>) t.getClass())这个地方报一个警告:
            // Unchecked cast: 'java.lang.Class<capture<? extends java.lang.Object>>' to 'java.lang.Class<? extends T>' 
            return queryRunner.query(connection,sql,new BeanHandler<T>((Class<? extends T>) t.getClass()),params);
        } finally {
            // 省略代码...
        }
    }

为什么在方式2会存在Unchecked cast警告?

这个异常提示是由于JAVA里的泛型擦除机制导致的。

在JAVA里,泛型类型经过编译实际上会被擦除,编译后JVM看到的只是原始类型或者是第一个边界的类型,也就是说:
方式1经过类型擦除后是这样的:

public Object queryOne(Class t, String sql, Object... params) throws SQLException {
    try {
        return queryRunner.query(connection, sql, new BeanHandler(t), params);
    } finally {
        // 省略代码...
    }
}

方式2经过类型擦除后是这样的:

public Object queryOne(Object t, String sql, Object... params) throws SQLException {
    try {
        return queryRunner.query(connection, sql, new BeanHandler((Class) t.getClass()), params);
    } finally {
        // 省略代码...
    }
}

方式二在运行时无法获取泛型具体类型,所以需要使用强制转换来将参数类型转换为 Class<? extends T>。如果传递的参数类型与实际类型不匹配,则可能会在运行时出现 ClassCastException 异常,存在一定的类型安全风险。
所以如果你能保证你传入的参数类型一定是正确的,可以使用@SuppressWarnings("unchecked")加在方法上来消除这条异常提示。

回答

相关文章

nuxt2部署静态化和ssr的时候访问首页先报404再出现首页为什么?
`clip-path` 如何绘制圆角平行四边形呢?
多线程wait方法报错?
VUE 绑定的方法如何直接使用外部函数?
vue2固定定位该怎么做?
谁有redis实现信号量的代码,希望借鉴一下?