面试题答案
一键面试Java代码实现
class BaseClass {
public void baseMethod() {
System.out.println("This is a base method.");
}
}
class SubClass1 extends BaseClass {
@Override
public void baseMethod() {
System.out.println("This is SubClass1's implementation of base method.");
}
}
class SubClass2 extends BaseClass {
@Override
public void baseMethod() {
System.out.println("This is SubClass2's implementation of base method.");
}
}
class GenericClass<T extends BaseClass> {
private T instance;
public GenericClass(T instance) {
this.instance = instance;
}
public void callBaseMethod() {
instance.baseMethod();
}
}
public class Main {
public static void main(String[] args) {
GenericClass<SubClass1> subClass1GenericClass = new GenericClass<>(new SubClass1());
GenericClass<SubClass2> subClass2GenericClass = new GenericClass<>(new SubClass2());
subClass1GenericClass.callBaseMethod();
subClass2GenericClass.callBaseMethod();
}
}
多态性体现
在上述代码中,GenericClass
接受一个继承自BaseClass
的泛型参数T
。通过创建GenericClass<SubClass1>
和GenericClass<SubClass2>
的实例,并调用callBaseMethod
方法,实际调用的是SubClass1
和SubClass2
各自重写的baseMethod
,这体现了多态性。
类型擦除影响及应对
- 影响:Java泛型在编译后会进行类型擦除,即泛型类型信息在运行时会丢失。例如,上述代码编译后,
GenericClass
中的T
会被擦除为BaseClass
。这可能导致在运行时无法获取准确的泛型类型信息,比如不能使用instanceof
操作符来判断具体的泛型类型。 - 应对方式:
- 使用通配符:可以使用通配符
?
来在一定程度上处理类型擦除问题。例如,GenericClass<? extends BaseClass>
可以接受任何继承自BaseClass
的类型。 - 传递Class对象:可以在构造函数中传递
Class<T>
对象,以便在运行时获取泛型类型信息。如下修改GenericClass
:
- 使用通配符:可以使用通配符
class GenericClass<T extends BaseClass> {
private T instance;
private Class<T> clazz;
public GenericClass(Class<T> clazz) {
this.clazz = clazz;
}
public void createInstance() throws IllegalAccessException, InstantiationException {
this.instance = clazz.newInstance();
}
public void callBaseMethod() {
if (instance != null) {
instance.baseMethod();
}
}
}
然后在main
方法中:
public class Main {
public static void main(String[] args) throws IllegalAccessException, InstantiationException {
GenericClass<SubClass1> subClass1GenericClass = new GenericClass<>(SubClass1.class);
subClass1GenericClass.createInstance();
subClass1GenericClass.callBaseMethod();
GenericClass<SubClass2> subClass2GenericClass = new GenericClass<>(SubClass2.class);
subClass2GenericClass.createInstance();
subClass2GenericClass.callBaseMethod();
}
}
通过传递Class
对象,可以在运行时创建具体类型的实例,部分解决类型擦除带来的问题。