Search code examples
javagenericslambdafunctional-interface

How to pass Object object in functional interface/lambda call


So, I have a piece of code that goes like

public static void printStuff(Object[] stuffs, Function<?, String> func) {
    for(Object stuff : stuffs) {
        String stringStuff = func.apply(stuff);
        System.out.println(stringStuff);
        // or whatever, what is done with that String is not relevant
    }
    // ...

This method is to be called with arrays of different types, and corresponding func value, for example:

printStuff(arrayOfClasses, (Class<?> c) -> c.getSimpleName());
printStuff(arrayOfStrings, (String s) -> '"' + s + '"');
printStuff(arrayOfObjects, o -> o.toString());

so I definitely need my stuffs to be Object[], because it is the first common superclass of the different types amongst the method's calls.

And on compilation, I get:

MyClass.java:6: error: incompatible types: Object cannot be converted to CAP#1
        String stringStuff = func.apply(stuff);
                                        ^
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?

My guess is that javac rants for the parameter I give to the Function<?, String> call, whose type, Object, does not extend Object.

So my question is, how can I pass an Object parameter to a Function<?, String>?

I can change the interface types to <Object, String>, but it breaks my others calls (with Class[], String[], etc) and it would imply losing pretty much the whole point of genericity, wouldn't it?

Unless there is some way to change my stuffs type to something like <? extends Object>[], or a generic type, and I'm pretty sure it's not possible.

Thanks in advance, folks.

EDIT:

if I change my method to a generic one, i.e.:

public static <U> void printStuff(Object[] stuffs, Function<U, String> func) {

I still get a compilation error :

MyClass.java:6: error: method apply in interface Function<T,R> cannot be applied to given types;
            String stringStuff = func.apply(stuff);
                                     ^
  required: U
  found: Object
  reason: argument mismatch; Object cannot be converted to U

Solution

  • One solution would be to use:

    public static <T> void printStuff(T[] stuffs, Function<T, String> func) {
        for(T stuff : stuffs) {
            // ....