我有一个数据库类,其中封装了java.sql.*
类的功能。基本上,您可以将其子类化以创建到特定数据库的连接,然后可以使用其方法执行常见操作。
我要实现的一种操作是getColumn()
方法。如果预期的数据库列是String数据类型,则可以执行以下操作:
public List<String> getColumn(String sql) throws SQLException
{
List<String> results = new ArrayList<>();
ResultSet rs = _stmt.executeQuery(sql);
while (rs.next())
{
results.add(rs.getString(1));
}
return results;
}
但是我想使用模板参数来泛化此方法,并使用适当的ResultSet.get*
方法填充ArrayList
。
类似这样的东西:
public <T> List<T> getColumn(String sql) throws SQLException
{
List<T> results = new ArrayList<>();
ResultSet rs = _stmt.executeQuery(sql);
while (rs.next())
{
// if T is String, do:
// results.add(rs.getString(1));
// if T is Integer, do:
// results.add(rs.getInt(1));
// etc.
}
return results;
我确信必须有一种优雅的方法来做到这一点。有什么想法吗?我会以错误的方式处理吗? }
答案 0 :(得分:1)
这是一种方法,
public <T> List<T> getColumn(String sql) throws SQLException {
List<T> results = new ArrayList<>();
ResultSet rs = _stmt.executeQuery(sql);
while (rs.next()) {
@SuppressWarnings("unchecked")
final T colVal = (T) rs.getObject(1);
results.add(colVal);
}
return results;
}
答案 1 :(得分:1)
一个常见的错误是尝试使用签名如下的方法:
<T> T fn()
在Java中,无法在fn
的调用中找出什么T
。选项包括返回null
,不安全地强制转换可能为T
的对象或引发异常。如果您有类似的东西,但是返回类型为List<T>
,那么您可以存储在该列表中的唯一内容就是null
。
那该怎么办。通常,您将传入一个参数以创建所需的类型。例如,一个功能对象。 (我会使用java.util.function.Function
,但检查的异常会妨碍您。)
List<String> names = getColumn(
"SELECT [...]",
(result, column) -> result.getString(column)
);
[...]
interface ResultFunction<T> {
T get(ResultSet results, int column) throws SQLException;
}
public <T> List<T> getColumn(
String sql, ResultFunction<T> function
) throws SQLException {
List<T> values = new ArrayList<>();
try (ResultSet result = _stmt.executeQuery(sql)) {
while (result.next()) {
values.add(function.get(result, 1));
}
}
return values;
}
您可能想扩展ResultFunction
的功能并可能使用枚举。