Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing generic function to a generic method [duplicate]

Tags:

java

generics

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); where T is a type variable T extends Object declared in method getSomeValue(boolean)

It complains similarly about the 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.

like image 558
David Avatar asked Jan 26 '26 18:01

David


1 Answers

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. That means that a caller can only bind Number or any subtype of Number to T when invoking the method. 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. If I invoked the method as

Float f = genOp.getSomeValue(true);

T should have been 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). 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. That means that you can bind any type to T, which makes the problem even greater. I can now do

String f = genOp.getSomeValue(true);
like image 97
Sotirios Delimanolis Avatar answered Jan 28 '26 12:01

Sotirios Delimanolis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!