Java中的动态强制转换

时间:2010-10-15 02:27:19

标签: java dynamic generics casting

在我不做功课之前,我一直无法找到关于Java泛型和动态投射的众多问题的任何线索。

标量类型定义如下:

public class Scalar <T extends Number> {

  public final String name;

  T value;

  ... 

  public T getValue() {
    return value;
  }

  public void setValue(T val) {
    this.value = val;      
  }

}

我想有一个看起来像这样的方法:

public void evilSetter(V val) {
  this.value = (T) val;
}

当然,这通常是气馁的。我想要这样一个方法的原因是因为我有一组Scalars,我想稍后更改它们的值。但是,一旦进入集合,就无法再访问其泛型类型参数。因此,即使我想在运行时创建一个完全有效的赋值,也无法知道它在编译时是否有效,无论是否有泛型。

Map<String, Scalar<? extends Number>> scalars = ...;

Scalar<? extends Number> scalar = scalars.get("someId");

// None of this can work
scalar.value = ...
scalar.setValue(...)

那么我该如何实现一个经过检查的强制转换和设置方法呢?

public <V extends Number> void castAndSet(V val) {
    // One possibility
    if (this.value.getClass().isAssignableFrom(val.getClass()) {
       // Some cast code here
    }
    // Another
    if (this.value.getClass().isInstanceOf(val) {
       // Some cast code here    
    }
    // What should the cast line be?
    // It can't be:
    this.value = this.value.getClass().cast(val);
    // Because this.value.getClass() is of type Class<?>, not Class<T>        

}

所以我离开了

this.value = (T) val;

并捕获ClassCastException?

1 个答案:

答案 0 :(得分:3)

你有:

this.value.getClass().isAssignableFrom(val.getClass())

除非您确定value永远不会为空,否则这可能会成为一个问题。

您还有:

this.value = (T) val;

这只会转发到Number而不是T,因为由于类型删除,引擎T只是Number。因此,如果valueDoublevalInteger,则不会抛出异常。

如果您确实想要执行已检查广告投放,则必须拥有正确的Class<T>对象。这意味着您应该在对象的构造函数中传递Class<T>。 (除非你可以确定value永远不会为空,在这种情况下你可以按照你的第一个想法。)一旦你有了这个对象(存储在一个字段中),你就可以执行检查的强制转换:

T value = valueClass.cast(val);
相关问题