You should read the Java Tutorial on Lambda Expressions, Functional Interfaces, and Method References to get a basic understanding of what the code in that example does. When you add
new FooA() to a map, you're adding a single instance of an object. Getting it back out of the map does not create any new instances. On the other hand, Foo::new is a method reference that gets turned into an implementation of a Functional Interface. Explaining these concepts is going to be way too long, so it's best that you go to the tutorials to bone up on those concepts.
Short version:
FooA::new is NOT equivalent to
new FooA(). There's a whole lot of "magic" that happens when the compiler processes FooA::new and what happens depends a lot on the context in which it is used.
In the case of
noArgs.put("A", FooA::new), since noArgs is declared as a Map<String, Supplier<Foo>>, the
Supplier<Foo> part dictates that
FooA::new is compiled into something that is essentially this:
This is why you have
noArgs.get(kind).get() as the return value for the factory method
FooFactory.get(String kind).
In the case of
withArg.put("A", FooA::new), since withArg is declared as a Map<String, Function<String, Foo>>, the
Function<String, Foo> part dictates that
FooA::new is compiled into something that is essentially this:
This is why you have
withArg.get(kind).apply(value) as the return value for the factory method
FooFactory.get(String kind, String value).