But these days it seems like Java is engaged in one long apology for the "everything is an object" mindset it started out with. It both took it too far and not far enough. Erased generics were the start of the problem. Parametric types! You were the chosen one! You were supposed to unify the primitive types and the object types! And never adding syntax for function types, just single-method interfaces...just ugly and clunky IMHO.
C# did generics right. Well, almost. "void" isn't a real type, so you can't be generic over it.
It is really important in language design that generics can range over any type. It allows the full combinatorial space. I worked really hard to make the Virgil compiler support arbitrary combinations of tuples, arrays, function types, and all of those work together seemlessly in the polymorphic type system. Everything else is a unfortunate shortcut, IMHO.