面试题答案
一键面试1. Java 如何通过类型擦除实现多态
在Java中,泛型是通过类型擦除机制来实现的。类型擦除意味着在编译阶段,所有的泛型类型信息都会被擦除,替换为它们的原始类型(raw type)。
对于 GenericClass<T>
,擦除后变为 GenericClass
,其 print(T t)
方法变为 print(Object t)
。
当 SubGenericClass1
继承 GenericClass<String>
时,在字节码层面,它的 print(String t)
方法实际上是 print(Object t)
,但由于Java的方法重写机制,在运行时,JVM会根据对象的实际类型来调用正确的方法。即当 SubGenericClass1
的实例调用 print
方法时,会调用 SubGenericClass1
中重写的 print(String t)
方法(尽管字节码层面是 print(Object t)
),这就实现了多态。
同理,SubGenericClass2
继承 GenericClass<Integer>
,字节码层面 print(Integer t)
变为 print(Object t)
,但运行时根据对象实际类型调用 SubGenericClass2
中重写的 print(Integer t)
方法。
2. 可能遇到的问题
- 类型安全性降低:由于类型擦除,在运行时无法获取泛型的实际类型参数。这可能导致在运行时发生
ClassCastException
。例如,如果在使用泛型时不小心将错误类型的数据放入集合中,编译时不会报错,但运行时可能会因为类型转换失败而抛出异常。 - 桥接方法问题:在某些复杂的继承和泛型组合场景下,编译器可能会生成桥接方法(bridge method)来维护多态性。这些桥接方法可能会使字节码变得复杂,并且在调试和理解代码时增加难度。例如,当子类重写父类的泛型方法并且返回类型是协变的(子类型)时,编译器会生成桥接方法来确保多态性的正确实现。但这种情况下,开发者可能会看到一些看似多余或难以理解的方法调用,因为桥接方法在字节码层面做了额外的处理。