Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

return generic type from generic function

we have a method more or less like the following. however we currently return List which in function bla() would return List<Bar> at runtime.

I'm looking for a way to make both

List<Interface> =  troubleFuction(foo, bar.getCLass());;

and

List<Bar> = troubleFuction(foo, bar.getCLass());;

possible. basicaly i want it to return List which would be compatible with interface however this gives the following error

*Type mismatch: cannot convert from List<capture#3-of ? extends Bar> to List<Interface>*

is there any way to make this return type possible or does runtime erasure make this impossible

public <T1 extends Interface, T2 extends Interface> List<"problem"> troubleFunction( T1 in, Class<T2> clazz) {
  return in.doStuffWhichGeneratesAlistOF(clazz)
}

public void bla() {
  Foo foo = new Foo(); // implements interface
  Bar bar = new Bar(); // implements interface
  List<Interface> ifaces = toubleFuction(foo, bar.getCLass());
  List<Bar> mustAlsoWork = toubleFuction(foo, bar.getCLass());
}

edit: in a lot of the existing code base the method is called like

List<Bar> result = troubleFunction(List<Interface> list, Bar.class);

thus this return type must stay compatible (rewrite/re-factor is not an option)

essentially i want the method to return List<? super Bar> if called as

troublefunction(foo, Bar.class);

and List<? super Foo> when called as

troublefunction(foo, Bar.class);
like image 800
pvgoddijn Avatar asked Mar 13 '26 21:03

pvgoddijn


2 Answers

Generally speaking in situations like this, you need to explicitly pass a Class object in (generically parameterised) which is used for the return value.

However it looks like you've done this already in your case, so would it not work for troubleFunction to be declared to return List<T2>? Alternatively, if you want to keep it general then have it return List<? extends Interface>.

like image 138
Andrzej Doyle Avatar answered Mar 16 '26 09:03

Andrzej Doyle


You're not giving us enough information to really tell what you need to do. For example, you didn't give us the type signature of doStuffWhichGeneratesAlistOF() or tell us what it does. And you didn't tell us what the type of the "in" argument has to do with all of this.

Sure, it's possible to have the return type of a method be generic. For example,

public <T extends Interface> List<T> troubleFunction(Interface in, Class<? extends T> clazz) {
  List<T> result = new ArrayList<T>();
  result.add(clazz.newInstance());
  return result;
}

And then you could call the method directly like this and it would work (you don't need to specify the type parameter explicitly because it's inferred from the assignment):

List<Interface> iface = this.troubleFunction(foo, bar.getCLass());

But seeing as how in your code above you return the result of in.doStuffWhichGeneratesAlistOF(clazz), you would probably have to make the return type of that method generic also. But I can't really help you on that because we don't have any information on that method.

like image 41
newacct Avatar answered Mar 16 '26 10:03

newacct



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!