Java类型擦除探究:JShell中泛型类两种调用场景的疑问
Great question—this difference all comes down to raw types and how Java's type erasure works under the hood. Let's break this down step by step using your two scenarios.
Scenario 1: Using the Parameterized Type X<Integer>
X<Integer> w = new X<Integer>(); w.id(5); // Outputs: 5
When you use the parameterized type X<Integer>, the compiler handles two key details:
- At compile time, it parameterizes the
idmethod toInteger id(Integer a), enforcing strict type checks (you can’t pass a non-Integer value here without a compile error). - After type erasure (Java’s process of stripping generic info at compile time), the runtime method is still
Object id(Object a)—but the compiler automatically inserts a cast to Integer when the method returns.
JShell receives an explicitly typed Integer result, so it simply outputs the numeric value 5 with no extra context, exactly as you’d expect.
Scenario 2: Using the Raw Type X
X x = new X<Integer>(); x.id(5); // Outputs: 5 plus additional content
Here you’re using a raw type (omitting the generic parameter <Integer> from the variable declaration X x). Raw types exist to support pre-Java 5 code, and they disable all generic type checks and automatic conversions:
- At compile time, the compiler treats
Xas a non-generic class, so theidmethod’s signature is erased toObject id(Object a). No type checking happens here—you could even pass aStringlikex.id("test")and it would compile without errors. - At runtime,
5is autoboxed toInteger(which is anObject), passed to the method, and returned as anObject(even though the underlying instance is stillInteger).
The "extra content" you see in JShell stems from it handling an Object-typed return value instead of an Integer. Since the type isn’t narrowed down at compile time, JShell may display additional context about the object’s runtime type (or track it as an Object in its variable history) to reflect that the compiler didn’t enforce a specific type here.
The Core Link to Type Erasure
Java’s generics are a compile-time only feature—type erasure removes all generic type information before the code runs:
- For parameterized types, the compiler adds synthetic casts to simulate the generic behavior, making the result feel like a specific type (e.g.,
Integer). - For raw types, we skip those casts and type checks, so we’re working directly with the erased
Objecttype at both compile and runtime. This is why JShell shows extra information: it’s revealing the raw, erased type behavior instead of the "sugared" generic experience.
内容的提问来源于stack exchange,提问作者Mohideen Imran Khan

