我想写一个类型安全的代码。以下是我尝试过的内容:
public interface ResultTronsformer<T>{
public T tranform(T t);
}
public class BigDecimalTransformer implements ResultTRansformer<BigDecimal>{
public BigDecimal transform(BigDecimal t){
return t.setScale(0);
}
}
现在我定义了类似
的Column接口public interface Column{
public ResultTransformer<?> getTransformer();
}
并希望在方法
中使用它public class Report{
private Map<Column, Object> columnValuePairs;
public void putIntoACollection(Column c, Object columnsValue){
ResultTransformer<?> rt = c.getTransformer();
columnValuePairs.put(c, rt.transform(o)); //Error: Couldn't convert Object
//to the capture of wildcard
}
}
如何重新设计设计以达到理想的类型安全性?也许我应该在运行时进行类型检查(抛出异常)?
答案 0 :(得分:2)
您可以将列视为某种具有特定类型的容器。这样,您可以在Column声明中引入泛型类型。
public interface Column<T>{
public ResultTransformer<T> getTransformer();
}
然后,您可以按如下方式更改Report方法:
public <T> void putIntoACollection(Column<T> c, T columnsValue){
ResultTransformer<T> rt = c.getTransformer();
columnValuePairs.put(c, rt.transform(columnsValue));
}
答案 1 :(得分:1)
您可以更改Column
类并使其参数化:
public interface Column<T> {
public ResultTransformer<T> getTransformer();
}
然后你必须参数化putIntoACollection
方法(不需要参数化Report
):
public class Report {
private Map<Column, Object> columnValuePairs;
public <T> void putIntoACollection(Column<T> c, T columnsValue) {
final ResultTransformer<T> rt = c.getTransformer();
columnValuePairs.put(c, rt.transform(columnsValue));
}
}
这样,您永远不需要使用捕获类型。
以下是如何使用它的示例:
private class BigDecimalColumn implements Column<BigDecimal> {
@Override
public ResultTransformer<BigDecimal> getTransformer() {
return new BigDecimalTransformer();
}
}
public static void main(String[] args) {
final Report report = new Report();
report.putIntoACollection(new BigDecimalColumn(), new BigDecimal("3.14"));
}
答案 2 :(得分:1)
获得变换器时,需要指定类型,因为编译器当时不知道它。
一种可能的解决方案是将类作为参数添加到Column的getTransformer中,并返回一个专门的ResultTransformer。
public interface ResultTransformer<T> {
public T transform(T t);
}
public interface Column{
public <T> ResultTransformer<T> getTransformer(Class<T> theClass);
}
public class Report{
private Map<Column, Object> columnValuePairs;
public void putIntoACollection(Column c, Object o){
ResultTransformer<Object> rt = c.getTransformer(Object.class);
columnValuePairs.put(c, rt.transform(o));
}
public interface ResultTransformer<T> {
public T transform(T t);
}
另一种方法是概括接口Column。
答案 3 :(得分:0)
我们可以放弃所有的借口,只使用该死的原始类型
ResultTransformer rt = c.getTransformer();
更自命不凡的解决方案 -
static <T> T transform (ResultTransformer<T> rt, Object obj)
{
T t = (T)obj; // unchecked cast
return rt.transform(t);
}
public void putIntoACollection(Column c, Object obj){
ResultTransformer<?> rt = c.getTransformer();
columnValuePairs.put(c, transform(rt, obj) );
}