我正在尝试创建一个通用的JavaFX Service
,它将使用DbUtils' BeanListHandler
将ObservableList
传递回app GUI线程。目的是重用它来将许多表加载到不同bean类的许多不同列表中。
我遇到的问题是处理call()
Task
方法中的泛型。
ICINGBean
是一个抽象类,我正在处理的所有bean都继承了fromextend。
public class StaticDataFetcher extends Service<ObservableList<? extends ICINGBean>> {
private Class<? extends ICINGBean> beanClass;
@Override
protected Task createTask() {
DataGetter dget = new DataGetter();
dget.setBeanClass(beanClass);
return dget;
}
public Class<? extends ICINGBean> getBeanClass() { return beanClass; }
public void setBeanClass(Class<? extends ICINGBean> beanClass) { this.beanClass = beanClass; }
}
class DataGetter extends Task<ObservableList<? extends ICINGBean>> {
private Class<? extends ICINGBean> beanClass;
@Override
protected ObservableList<? extends ICINGBean> call() {
ObservableList<? extends ICINGBean> staticList;
staticList = FXCollections.observableArrayList();
ResultSetHandler<List<? extends ICINGBean>> handler;
handler = new BeanListHandler<? extends ICINGBean>(beanClass);
try {
List<? extends ICINGBean> resultList;
resultList = EntryPoint.getQRunner().query("SELECT * FROM ?", handler, beanClass.getSimpleName());
staticList = FXCollections.observableList(resultList);
} catch (SQLException ex) {
Logger.getLogger(DataGetter.class.getName()).log(Level.SEVERE, null, ex);
}
return staticList;
}
public Class<? extends ICINGBean> getBeanClass() { return beanClass; }
public void setBeanClass(Class<? extends ICINGBean> beanClass) { this.beanClass = beanClass; }
}
我得到的编译时错误是:
.../ICING/src/com/cccg/icing/StaticDataFetcher.java:55: error: unexpected type
handler = new BeanListHandler<? extends ICINGBean>(beanClass);
^
required: class or interface without bounds
found: ? extends ICINGBean
我很确定我只是搞砸了仿制品处理,但我不确定如何处理。我已经按照DbUtils示例页面上的listed example来使用BeanListHandler,用我认为合适的地方替换它使用泛型类型,但是我无法解决错误。
非常感谢任何帮助,谢谢!
根据Paul Bellora的有用建议,我能够解决这个问题。我为类声明了一个类型参数,并将其与菱形运算符一起使用。
public class StaticDataFetcher<T extends ICINGBean> extends Task<ObservableList<? extends ICINGBean>> {
private Class<T> beanClass;
//...
public StaticDataFetcher(Class<T> beanClass) {
super();
this.beanClass = beanClass;
}
protected ObservableList<? extends ICINGBean> call() {
//...
ResultSetHandler<List<T>> handler;
handler = new BeanListHandler<>(beanClass);
//...
}
}
感谢大家的帮助,我希望这有助于其他人!
答案 0 :(得分:1)
不允许使用通配符类型参数实例化泛型类型。在this answer中查看我对原因的解释。
一个简单的解决方案是使用diamond operator(Java 7及更高版本):
handler = new BeanListHandler<>(beanClass);
如果不可用,则需要使用通用帮助方法:
<T extends ICINGBean> BeanListHandler<T> makeContainer(Class<T> beanClass) {
return new BeanListHandler<T>(beanClass);
}
...
handler = makeContainer(beanClass);
答案 1 :(得分:0)
我努力让这个在Yank中正常运作。这是Java 6中对我有用的东西:
public static <T> List<T> queryObjectListSQL(String poolName, String sql, Class<T> type, Object[] params) {
List<T> returnList = null;
Connection con = null;
try {
con = DB_CONNECTION_MANAGER.getConnection(poolName);
if (con == null) {
throw new ConnectionException(poolName);
}
con.setAutoCommit(false);
BeanListHandler<T> resultSetHandler = new BeanListHandler<T>(type);
returnList = new QueryRunner().query(con, sql, resultSetHandler, params);
con.commit();
} catch (Exception e) {
logger.error(QUERY_EXCEPTION_MESSAGE, e);
try {
con.rollback();
} catch (SQLException e2) {
logger.error(ROLLBACK_EXCEPTION_MESSAGE, e2);
}
} finally {
DB_CONNECTION_MANAGER.freeConnection(poolName, con);
}
return returnList;
}
完整的源代码是here。上面的代码明显不同于您的确切示例,但您可以看到泛型如何工作。这样做的巧妙之处在于,在调用方法时根本不必进行强制转换。
我希望有所帮助。