问题
import java.util.List;
public class MyClass {
private List<String> list1;
private List<Integer> list2;
public MyClass(List<String> list1) {
this.list1 = list1;
}
public MyClass(List<Integer> list2) {
this.list2 = list2;
}
}
上述代码会导致编译错误:“both methods have same erasure”,因为在类型擦除后,两个构造函数的参数都变成了List,Java编译器无法区分它们。
解决方法
1. 引入额外的参数
通过添加一个额外的参数(哪怕是不被使用的参数),可以使得方法签名变得不同,从而解决冲突。但这种方法可能会让API使用起来有些奇怪。
2. 使用静态工厂方法
import java.util.List;
public class MyClass {
private List<String> list1;
private List<Integer> list2;
private MyClass(List<String> list1, List<Integer> list2) {
this.list1 = list1;
this.list2 = list2;
}
public static MyClass withStringList(List<String> list1) {
return new MyClass(list1, null);
}
public static MyClass withIntegerList(List<Integer> list2) {
return new MyClass(null, list2);
}
}
这样就可以通过MyClass.withStringList(someStringList)或MyClass.withIntegerList(someIntegerList)来创建MyClass的实例,同时避免了构造器重载的问题。
3. 使用一个泛型类
这种方法的好处是,它不仅避免了构造器重载导致的类型擦除问题,还提供了更加灵活和类型安全的方式来处理不同类型的数据。然而,使用这种方法时,需要注意的是,它可能会使原本的类设计变得更加复杂,特别是当类中涉及到多个这样的属性时。
4. 使用Builder模式
import java.util.List;
public class MyClass {
private List<String> list1;
private List<Integer> list2;
// 私有构造函数,防止外部直接创建实例
private MyClass(Builder builder) {
this.list1 = builder.list1;
this.list2 = builder.list2;
}
// 静态内部Builder类
public static class Builder {
private List<String> list1;
private List<Integer> list2;
// 设置List<String>并返回Builder实例
public Builder withList1(List<String> list1) {
this.list1 = list1;
return this;
}
// 设置List<Integer>并返回Builder实例
public Builder withList2(List<Integer> list2) {
this.list2 = list2;
return this;
}
// 构建最终的MyClass实例
public MyClass build() {
return new MyClass(this);
}
}
// 用于测试的main方法
public static void main(String[] args) {
// 使用Builder模式创建MyClass的实例
MyClass myClass = new MyClass.Builder()
.withList1(List.of("String1", "String2"))
.withList2(List.of(1, 2, 3))
.build();
// 测试输出,验证属性是否正确设置
System.out.println(myClass.list1);
System.out.println(myClass.list2);
}
}
使用Builder模式的好处是,它提供了一种更灵活的方式来构建对象,特别是当对象有多个属性需要设置时。此外,它还可以增强代码的可读性和易用性。