Generics and dispatchsenior8+ years

`interface Parser<T> { T parse(String s); }` and `class IntParser implements Parser<Integer> { public Integer parse(String s) { return Integer.valueOf(s); } }` — `javap -p IntParser` shows *two* `parse` methods in the class file, not one. Neither is dead code. What produced the second one, and which one actually runs when a caller holds a `Parser<Integer>` reference?

Generics are erased at compile time, so after erasure, Parser<T>'s parse method is really Object parse(String) in the class file — the type parameter T has no runtime representation, and the interface's bytecode-level signature uses T's erasure, Object, as the return type. IntParser.parse is declared to return Integer, which is a genuinely different method descriptor than Object parse(String) at the JVM level, so it does not, technically, override the interface method by descriptor-matching alone. javac closes that gap itself by generating a second, synthetic bridge method — Object parse(String) — that simply calls the real Integer-returning one and returns its result. A call made through the interface-typed reference (Parser<Integer> p = new IntParser(); p.parse("1")) resolves, at the bytecode level, to the bridge, which immediately forwards to the real method — invisible to the caller, and invisible in ordinary source-level reasoning, but present in every class file the compiler generates for a generic override like this one.

The lesson behind it →