Java 中的动态转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3939054/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:02:44  来源:igfitidea点击:

Dynamic casting in Java

javadynamicgenericscasting

提问by dgorur

Before I get chided for not doing my homework, I've been unable to find any clues on the multitude of questions on Java generics and dynamic casting.

在我因为没有做作业而受到责备之前,我一直无法找到有关 Java 泛型和动态转换的众多问题的任何线索。

The type Scalar is defined as follows:

Scalar 类型定义如下:

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

}

I would like to have a method that looks like this:

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

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

Sure, this is generally discouraged. The reason I want such a method is because I have a collection of Scalars whose values I'd like to change later. However, once they go in the collection, their generic type parameters are no longer accessible. So even if I want make an assignment that's perfectly valid at runtime, there's no way of knowing that it'll be valid at compile time, with or without generics.

当然,这通常是不鼓励的。我想要这种方法的原因是因为我有一组标量,我想稍后更改其值。然而,一旦它们进入集合,它们的泛型类型参数将不再可访问。因此,即使我想进行一个在运行时完全有效的赋值,也无法知道它在编译时是否有效,无论是否使用泛型。

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

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

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

So how do I implement a checked cast and set method?

那么如何实现一个checked cast和set方法呢?

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>        

}

So I'm left with using

所以我只剩下使用

this.value = (T) val;

and catching a ClassCastException?

并捕获 ClassCastException?

回答by Kirk Woll

You have:

你有:

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

This is probably going to be a problem unless you can be certain valuewill never be null.

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

You also have:

你还有:

this.value = (T) val;

This will only cast to Numberand not to Tbecause under the hood Tis just a Numberdue to type-erasure. Therefore if valueis a Doubleand valis an Integer, no exception will be thrown.

这只会投射到Number而不是T因为在引擎盖T下只是Number由于类型擦除。因此,如果value是 aDouble并且val是 an Integer,则不会抛出异常。

If you actually want to perform a checkedcast, you must have the correct Class<T>object. This means you should be passing Class<T>in the constructor of your object. (Unless you can be sure valueis never null, in which case you can go with your first idea.) Once you have that object (stored in a field), you can perform the checked cast:

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

T value = valueClass.cast(val);