This works perfectly fine in practice as can be seen using comparable constructs in C#, C++, and many other mainstream languages.
If anything it's more readable, since your code isn't littered with redundant type info.
I fail to see the redundant type info.
Example 1:
int maxWeight = blocks.stream() .filter(b -> b.getColor() == BLUE) .mapToInt(Block::getWeight) .max();
"int" is not redundant type info here.
Example 2:
List<String> list = new ArrayList<>(); // (1)
var list = new ArrayList<String>(); // (2)
Many would say List<String> in (1) is redundant but I would argue otherwise. The intention of List<String> in (1) is to reference to the underline ArrayList through List interface. (1) is trying to encourage programming to an interface while (2) just completely destroys the practice by inferring the type for list variable to be ArrayList<String>. That means subsequent method invocations after (2) can be methods from ArrayList not List.
So instead of doing this:
Foo foo = new Foo("bar");
You can do this: Foo foo = Foo.of("bar");If you were using a factory, var would infer the factory signature's type, which would normally be the interface.
So you think using functions is enterprisey and over-engineering things?
Actually, people left Java land because they couldn't express what they needed to without using complicated design patterns.
There is a point where typing becomes verbose and decreases readability. If the compiler can infer, it should. It'll save time, money, and sanity.