apache Commons Dbutils泛型應用及類型安全探討
在使用Apache Commons Dbutils進行數據庫操作時,為了提升代碼的可復用性和可讀性,我們通常會進行封裝,并使用泛型。然而,在使用queryOne方法時,泛型容易引發類型安全問題。本文將深入分析其原因,并給出解決方案。
問題根源在于queryOne方法的兩種不同泛型實現方式。第一種直接傳入class對象作為類型參數:
public <T> T queryOne(Class<T> clazz, String sql, Object... params) throws SQLException { try { return queryRunner.query(connection, sql, new BeanHandler<>(clazz), params); } finally { // 省略代碼... } }
第二種方式傳入泛型類型的對象實例:
public <T> T queryOne(T t, String sql, Object... params) throws SQLException { try { return queryRunner.query(connection, sql, new BeanHandler<T>((Class<? extends T>) t.getClass()), params); } finally { // 省略代碼... } }
第二種方式在new BeanHandler
其根本原因在于Java的類型擦除機制。編譯時,泛型信息會被擦除,運行時只保留原始類型。第一種方式中,Class
因此,t.getClass()返回的Class extends Object>無法安全地轉換為Class extends T>,需要強制轉換。雖然編譯可以通過,但運行時可能拋出ClassCastException異常。
使用@SuppressWarnings(“unchecked”)注解可以壓制警告,但這并不能解決潛在的類型安全問題。 只有確保傳入的t對象的實際類型與期望的T類型一致才能避免運行時異常。 因此,第一種方式,直接傳入Class