面试题答案
一键面试public class GenericOverloading {
// 方法重载,使用泛型类型参数
public <T> void printValue(T value) {
System.out.println("打印单个值: " + value);
}
public <T> void printValues(T[] values) {
System.out.println("打印值数组:");
for (T value : values) {
System.out.println(value);
}
}
public <T, U> void combine(T first, U second) {
System.out.println("组合值: " + first + " 和 " + second);
}
}
方法重载与泛型的相互作用
- 参数类型差异:在上述代码中,
printValue
方法接受单个泛型参数,printValues
方法接受泛型数组参数,combine
方法接受两个不同类型的泛型参数。这些方法通过参数的数量和类型(包括泛型类型的组合)来区分,满足方法重载的规则。 - 泛型类型擦除:在编译时,泛型类型会被擦除。但由于方法签名在编译期是完整的(包括泛型参数信息在签名中的体现),所以即使泛型类型被擦除,编译器仍然可以根据方法签名中的参数数量、类型及泛型参数的声明来区分不同的重载方法。
编译器的类型推断机制
- 显式类型声明:在调用泛型方法时,可以显式指定泛型类型,例如:
GenericOverloading go = new GenericOverloading();
go.<Integer>printValue(10);
- 隐式类型推断:编译器通常可以根据传递的参数类型来推断泛型类型。例如:
go.printValue(10); // 编译器推断T为Integer
go.printValues(new String[]{"a", "b"}); // 编译器推断T为String
go.combine("Hello", 5); // 编译器推断T为String,U为Integer
编译器会根据传入的实际参数类型,自动推断出合适的泛型类型,使得代码更加简洁易读。在复杂的情况下,可能需要显式指定泛型类型以避免编译错误或获得预期的行为。