繁体   English   中英

以类型安全的方式编写类

[英]Writing a class in a type-safe way

我想写一个类型安全的代码。 这是我尝试过的:

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
    }
}

如何重新设计设计以达到理想的类型安全性? 也许我应该在运行时进行类型检查(抛出异常)?

您可以考虑使用Column,就像它是某种具有特定类型的容器一样。 这样,您可以在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)); 
}

您可以更改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"));
}

获取转换器时,需要指定类型,因为编译器当时不会知道它。

一种可能的解决方案是将类作为参数添加到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。

我们可以放弃所有的借口,只使用该死的原始类型

     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) );

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM