简体   繁体   English

Java:转换为类型参数

[英]Java: Casting to a type parameter

I have the following two classes:我有以下两个类:

public class GenericNumberOperation {
    public GenericNumberOperation() {} 
    public <T extends Number> T getSomeValue (boolean tf) {
      T number;
      if(tf) {
          number = new Double(1.0);
      }
      else {
           number = new Integer(11);
      }
      return (T) number;
   }
}

And:和:

public class GenericNumberTest {
    public GenericNumberTest() {}

    public static void main(String[] args) {
        GenericNumberOperation gno = new GenericNumberOperation();
        Double d = gno.getSomeValue(true);
        Integer i = gno.getSomeValue(false);
    }
 }

When I run the test, everything is hunky-dory.当我运行测试时,一切都很正常。 If I change the type parameterization to:如果我将类型参数化更改为:

public <T> T getSomeValue(boolean tf)

The compiler complains, reporting:编译器抱怨,报告:

error: incompatible types Integer cannot be converted to T number = new Integer(11);错误:类型不兼容 Integer 不能转换为 T number = new Integer(11); where T is a type variable T extends Object declared in method getSomeValue(boolean)其中 T 是类型变量 T extends Object 在方法 getSomeValue(boolean) 中声明

It complains similarly about the Double.它对 Double 也有类似的抱怨。 Why?为什么?

EDIT: I made a mistake.编辑:我犯了一个错误。 This is actually the code that works.这实际上是有效的代码。

public class GenericNumberOperation {
    public GenericNumberOperation() {} 
    public <T extends Number> T getSomeValue (boolean tf) {
      Number number;
      if(tf) {
          number = new Double(1.0);
      }
      else {
           number = new Integer(11);
      }
      return (T) number;
   }
}

And now I understand what @Sotirios was getting at.现在我明白@Sotirios 的意思了。

Forget about what you're trying to use this for.忘记你想用它做什么。 We're only going to look at this from a language perspective.我们只会从语言的角度来看这个。

The declaration声明

public <T extends Number> T getSomeValue (boolean tf) {

defines a new type T that is bounded by Number .定义了一个以Number为边界的新类型T That means that a caller can only bind Number or any subtype of Number to T when invoking the method.这意味着,一个呼叫者只能绑定Number或任何亚型NumberT调用方法时。 Within the method, you don't know what that type might be.在该方法中,您不知道该类型可能是什么。

You therefore can't do你因此不能做

T number = new Double(1.0);

because you don't know that T is Double .因为你不知道TDouble If I invoked the method as如果我调用该方法为

Float f = genOp.getSomeValue(true);

T should have been Float . T应该是Float The compiler can't guarantee type safety and therefore rejects it (the assignment within the method, if it had been allowed, a ClassCastException would have been thrown at runtime).编译器无法保证类型安全,因此会拒绝它(方法中的赋值,如果允许的话,将在运行时抛出ClassCastException )。 If you use a cast, you're telling the compiler that you're sure about what you're doing.如果您使用强制转换,则是在告诉编译器您确定自己在做什么。 It'll warn you, but it will trust you.它会警告你,但它会信任你。

Similarly, the declaration同样,声明

public <T> T getSomeValue(boolean tf)

defines a new type T that is unbounded.定义了一个新的无界类型T That means that you can bind any type to T , which makes the problem even greater.这意味着您可以将任何类型绑定到T ,这使得问题更加严重。 I can now do我现在可以做

String f = genOp.getSomeValue(true);

As @Sotirios Delimanolis wrote, you cannot even run that code.正如@Sotirios Delimanolis 所写,您甚至无法运行该代码。

Try this one:试试这个:

@SuppressWarnings("unchecked")
public <T extends Number> T getSomeValue(boolean tf) {
    T number;
    if (tf) {
        number = (T) new Double(1.0);
    } else {
        number = (T) new Integer(11);
    }
    return number;
}

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

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