2017-07-19 170 views
3

我们假设我有四个类:Car,Convertible,PickupTruckCarManufacturerJava泛型调用构造函数

Car是抽象类,ConvertiblePickupTruck继承:

public abstract class Car { 
    private String name; 
    private String colour; 

    //Constructor 
} 

ConvertiblePickupTruck都有参数构造函数:

public class Convertible extends Car { 
    private boolean roofUnfolded; 

    public Convertible() { 
     super("Convertible", "Red"); 
     this.roofUnfolded = false; 
    } 
} 

public class PickupTruck extends Car { 
    private double capacity; 

    public PickupTruck() { 
     super("Pickup Truck", "Black"); 
     this.capacity = 100; 
    } 
} 

CarManufacturer商店要么ConvertiblesPickupTrucks的名单。

public class CarManufacturer <T extends Car>{ 
    private List<T> carsProduced = new LinkedList<>(); 
} 

我怎样才能实现一个功能produceCar()调用参数的构造函数和将对象添加到列表中?我想:

public void produceCar(){ 
    this.carsProduced.add(new T()); 
} 

返回错误:Type parameter 'T' cannot be instantiated directly

回答

5

同样的问题在这里得到解决: https://stackoverflow.com/a/36315051/7380270

至于这个问题,这个工程:

public class CarManufacturer <T extends Car> { 
    private Supplier<T> carType; 
    private List<T> carsProduced = new LinkedList<>(); 

    public CarManufacturer(Supplier<T> carType) { 
     this.carType = carType; 
    } 

    public void produceCar() { 
     this.carsProduced.add(carType.get()); 
    } 

} 

public class Main { 
    public static void main(String[] args) { 
     CarManufacturer<Convertible> convertibleCarManufacturer = new CarManufacturer<>(Convertible::new); 
     convertibleCarManufacturer.produceCar(); 
    } 
} 
2

您可以添加Class<T>CarsManufacturer,这将保留有关在运行时类型参数的元信息。这可能让你实例化T,通过Class#newInstance()方法:

public class CarManufacturer<T extends Car> { 

    private List<T> carsProduced = new LinkedList<>(); 

    private Class<T> clazz; 

    public CarManufacturer(Class<T> clazz) { 
     this.clazz = clazz; 
    } 

    public void produceCar() throws IllegalAccessException, InstantiationException { 
     this.carsProduced.add(clazz.newInstance()); 
    } 

} 

然后,您可以使用它像这样:

CarManufacturer<Convertible> carManufacturer = new CarManufacturer<>(Convertible.class); 
carManufacturer.produceCar(); 

即使这应该工作,记住,有几个注意事项值得一提:

  • 我不会使用Class<T>成员,只是为了在运行时访问类型参数替换。我宁愿将(T instance)参数添加到produceCar方法签名中,并直接将此实例添加到列表中。由于您通过明确指定类型参数来实例化CarManufactured,因此您无需保留Class<T>,因为您已经知道该参数是什么。
  • 我会将produceCar方法重命名为与该方法的更多相关内容 - 例如,saveCar()addCar()
+0

那么有比使用反射更好的方法,但仍然是一个有效的答案。 – Flown