1

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
6
  • 3
    can't you public static <T> void printStuff(T[] stuffs, Function<T, String> func) {?? Commented Aug 18, 2017 at 16:21
  • and the explanation. Commented Aug 18, 2017 at 16:28
  • nope, alas. See my edit Commented Aug 18, 2017 at 16:28
  • You didn't change your signature as RC proposed. Commented Aug 18, 2017 at 16:29
  • @Maaaatt oops, read too fast. works indeed -- as long as I don't forget to change the type of the inner for loop. Daaang, I was pretty sure type variables arrays were not possible though Commented Aug 18, 2017 at 16:37

2 Answers 2

4

One solution would be to use:

public static <T> void printStuff(T[] stuffs, Function<T, String> func) {
    for(T stuff : stuffs) {
        // ....
Sign up to request clarification or add additional context in comments.

1 Comment

You nailed it. Thanks!
2

As for the first code:

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

You are getting this error

MyClass.java:6: error: incompatible types: Object cannot be converted to CAP#1

You get that error because the ? could be any more specific class, e.g. you could also pass an argument func of type Function<String, String>.

You could fix that by declaring the signature like

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

or in a generic way:

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

It is essential that the type of the array is equal to (or a subclass of) the first type parameter of the Function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.