In principle, the compiler can optimize to the most efficient code. Mostly the types are “gatekeepers” during the compilation phase with little runtime overhead. Also, sometimes the types tell the compiler information so it can choose the most efficient algorithm to use, such as when doing arithmetic on “instances”. Dispatching to methods is naïvely slower than calling functions, because you have find the right implementation to call in a class hierarchy, but even there, the JVM (and probably other runtimes) often optimize this overhead away at runtime by watching which of the methods are actually called most of the time.