1

I'm currently working my way thorough Java Core book and I'm in the generic chapter. I can't grasp one thing here. As book states you cannot make a new object out of T in generic class, so this is not possible

public foo() { first = new T(); second = new T(); } //ERROR

What you can do is use functional interface and lambda expression with reference to constructor like this

foo<String> f = foo.makeFoo(String::new)

public static <T> foo<T> makeFoo(Supplier<T> constr)
{
    return new foo<>(constr.get(), constr.get());
}

And it's great, working as expected, but only with String, if I want to use with any other object, for example wrapped simple type Integer it's not possible. It gives me this error

Error:(35, 38) java: method makeFoo in class generic.foo<T> cannot be applied to given types;
required: java.util.function.Supplier<T>
found: Integer::new
reason: cannot infer type-variable(s) T
(argument mismatch; incompatible parameter types in method reference)

It seems only working with String and I have no idea why, I thought that it would work for every object

I'm trying to create all those objects on correct classes

  foo<String> fString = foo.makeFoo(String::new); //Works
  foo<Integer> fInteger = foo.makeFoo(Integer::new); //Doesn't work
  foo<Double> fDouble = foo.makeFoo(Double::new); //Doesn't work

EDIT

Actually this works with custom objects, only wrapped simple types won't compile

foo<MyCustomObject> fCustom = foo.makeFoo(MyCustomObject::new); //Works
M Tomczynski
  • 15,099
  • 1
  • 15
  • 25
  • 1
    The type of the variable `f` is `foo`, so obviously it expects that the supplier returns a `String` object. Change it to `foo` if you're giving it a supplier that returns an `Integer` object. – Jesper Dec 05 '16 at 10:37
  • I'm doing exactly that and this gives cannot applied error. foo fInteger = foo.makeFoo(Integer::new); – M Tomczynski Dec 05 '16 at 10:40
  • 1
    @MTomczyński I've rejected your edit of my answer as there was to much text/code I did not write. I think it would be better if you would have posted it as your own answer to your question, this is absolutely appropriate. – lexicore Dec 05 '16 at 11:08

2 Answers2

3

In contrast to String, there is no no-arg constructor of Integer. So Integer::new is not a Supplier<Integer>. makeFoo(Object::new) would work.

lexicore
  • 42,748
  • 17
  • 132
  • 221
1

As lexicore pointed we cannot make expression Integer::new, due to no no-arg constructor of Integer object. Correct syntax with integer can be as simple as this, where arg being int variable

foo<Integer> f = foo.makeFoo(() -> (arg));

Wrapping in new Integer(arg) is unnecessary here.

More info on the topic: Java 8 Supplier with arguments in the constructor

Community
  • 1
  • 1
M Tomczynski
  • 15,099
  • 1
  • 15
  • 25