【问题标题】:Method with generic return具有通用返回的方法
【发布时间】:2016-08-26 13:09:06
【问题描述】:

我在编写具有通用返回值的方法时遇到了困难。我想有一个方法,当用MachineMorphology 实例调用时返回一个M 类型的实例,其中M 是MachineMorphology 泛型类型。

这可以实现吗?

MachineMorphology.java

public interface MachineMorphology<M extends Machine> {

    Class<? extends M> getClazz();
}

ExtrusionMachinesMorphology.java

public final class ExtrusionMachinesMorphology<M extends Machine> implements MachineMorphology<M> {
    public static final ExtrusionMachinesMorphology<Doser> DOSER = new ExtrusionMachinesMorphology<>(Doser.class);
    public static final ExtrusionMachinesMorphology<Extruder> EXTRUDER = new ExtrusionMachinesMorphology<>(Extruder.class);
    public static final ExtrusionMachinesMorphology<Blower> BLOWER = new ExtrusionMachinesMorphology<>(Blower.class);
    public static final ExtrusionMachinesMorphology<Die> DIE = new ExtrusionMachinesMorphology<>(Die.class);
    public static final ExtrusionMachinesMorphology<HaulOff> HAULOFF = new ExtrusionMachinesMorphology<>(HaulOff.class);
    public static final ExtrusionMachinesMorphology<Winder> WINDER = new ExtrusionMachinesMorphology<>(Winder.class);
    public static final ExtrusionMachinesMorphology<FilmMeasurer> MEASUSER = new ExtrusionMachinesMorphology<>(FilmMeasurer.class);
    public static final ExtrusionMachinesMorphology<AirRing> AIR_RING = new ExtrusionMachinesMorphology<>(AirRing.class);
    public static final ExtrusionMachinesMorphology GEC = null;
    public static final ExtrusionMachinesMorphology UNDEFINED = null;

    private final Class<M> clazz;

    public ExtrusionMachinesMorphology(Class<M> clazz) {
        this.clazz = clazz;
    }

    public Class<? extends M> getClazz() {
        return clazz;
    }
}

AbstractExtrusionPlant.java

public abstract class AbstractPlant<T extends PlantType, S extends PlantStatus, O extends PlantOperatorStatus, A extends Alarm> 
    extends ListenableObject<AlarmsListener<Machine, A>> {

    [...]

    private volatile HashMap<MachineMorphology, List<? extends Machine>> machines = new HashMap<>();

    public synchronized <M extends Machine> M getMachine(MachineMorphology<M> morphology, int unitId) {
        return getMachineByUnitId(getMachinesByMorphology(morphology), unitId);
    }

    public synchronized <M extends Machine> M getMachineByUnitId(List<M> machines, int unitId) {
        return machines.stream().filter(machine -> machine.getUnitId() == unitId).findFirst().orElse(null);
    }

    public synchronized <M extends Machine> List<M> getMachinesByMorphology(MachineMorphology<M> morphology) {
        return (List<M>) machines.get(morphology);
    }

    [...]
}

这应该是使用方法

Doser doser = plant.getMachine(ExtrusionMachinesMorphology.DOSER, 1);

但是编译器想要:

 Doser doser = (Doser)plant.getMachine(ExtrusionMachinesMorphology.DOSER, 1);

【问题讨论】:

  • 我认为工厂模式不适合我的情况,因为我需要一个带有通用机器列表的类(由带有 HashMap 的 MachineMorphology 排序),所以当我调用 getter 时,我需要指定形态和 unitId(如索引)以投射机器实例
  • 如果您的问题有解决方案,请鼓励将其添加为答案。不要在标题中使用“已解决”来表示您有解决方案;接受答案就足够了。

标签: java generics methods parameters


【解决方案1】:

我相信您在问 Map 是否可以返回具有不同泛型类型的对象。答案是否定的,不可能,但是你可以使用 Morphology 的类型在返回 List 之前对其进行转换:

public synchronized <M extends Machine> List<M> getMachinesByMorphology(MachineMorphology<M> morphology) {
    Class<? extends M> machineType = morphology.getClazz();
    return machines.get(morphology).stream().map(machineType::cast).collect(Collectors.toList());
}

更新:这是我用于测试可编译性的完整文件:

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

class Machine {
    int getUnitId() { return 0; }
}

class PlantType { }
class PlantStatus { }
class PlantOperatorStatus { }
class Alarm { }
class Doser extends Machine { }
class Extruder extends Machine { }
class Blower extends Machine { }
class Die extends Machine { }
class HaulOff extends Machine { }
class Winder extends Machine { }
class FilmMeasurer extends Machine { }
class AirRing extends Machine { }

interface AlarmsListener<M, A> { }
class ListenableObject<T> { }

interface MachineMorphology<M extends Machine> {

    Class<? extends M> getClazz();
}

final class ExtrusionMachinesMorphology<M extends Machine> implements MachineMorphology<M> {
    public static final ExtrusionMachinesMorphology<Doser> DOSER = new ExtrusionMachinesMorphology<>(Doser.class);
    public static final ExtrusionMachinesMorphology<Extruder> EXTRUDER = new ExtrusionMachinesMorphology<>(Extruder.class);
    public static final ExtrusionMachinesMorphology<Blower> BLOWER = new ExtrusionMachinesMorphology<>(Blower.class);
    public static final ExtrusionMachinesMorphology<Die> DIE = new ExtrusionMachinesMorphology<>(Die.class);
    public static final ExtrusionMachinesMorphology<HaulOff> HAULOFF = new ExtrusionMachinesMorphology<>(HaulOff.class);
    public static final ExtrusionMachinesMorphology<Winder> WINDER = new ExtrusionMachinesMorphology<>(Winder.class);
    public static final ExtrusionMachinesMorphology<FilmMeasurer> MEASUSER = new ExtrusionMachinesMorphology<>(FilmMeasurer.class);
    public static final ExtrusionMachinesMorphology<AirRing> AIR_RING = new ExtrusionMachinesMorphology<>(AirRing.class);
    public static final ExtrusionMachinesMorphology<?> GEC = null;
    public static final ExtrusionMachinesMorphology<?> UNDEFINED = null;

    private final Class<M> clazz;

    public ExtrusionMachinesMorphology(Class<M> clazz) {
        this.clazz = clazz;
    }

    public Class<? extends M> getClazz() {
        return clazz;
    }
}

public abstract class AbstractPlant<T extends PlantType, S extends PlantStatus, O extends PlantOperatorStatus, A extends Alarm> 
    extends ListenableObject<AlarmsListener<Machine, A>> {

    private volatile HashMap<MachineMorphology<? extends Machine>, List<? extends Machine>> machines = new HashMap<>();

    public synchronized <M extends Machine> M getMachine(MachineMorphology<M> morphology,
                                                         int unitId) {
        return getMachineByUnitId(getMachinesByMorphology(morphology), unitId);
    }

    public synchronized <M extends Machine> M getMachineByUnitId(List<M> machines, int unitId) {
        return machines.stream().filter(machine -> machine.getUnitId() == unitId).findFirst().orElse(null);
    }

    public synchronized <M extends Machine> List<M> getMachinesByMorphology(MachineMorphology<M> morphology) {
        Class<? extends M> machineType = morphology.getClazz();
        return machines.get(morphology).stream().map(machineType::cast).collect(Collectors.toList());
    }

    public static void main(String[] args) {
        AbstractPlant<PlantType, PlantStatus, PlantOperatorStatus, Alarm> plant =
            new AbstractPlant<PlantType, PlantStatus, PlantOperatorStatus, Alarm>() { };

        Doser doser = plant.getMachine(ExtrusionMachinesMorphology.DOSER, 1);
    }
}

【讨论】:

  • 有什么方法可以通过形态学和 unitId 返回铸造机器实例?就像我的例子:Doser doser = plant.getMachine(ExtrusionPlantMachinesMorphology.DOSER, 1);
  • 我能够成功编译行Doser doser = plant.getMachine(ExtrusionMachinesMorphology.DOSER, 1);。但是,我在您的问题中使用了名为 ExtrusionMachinesMorphology 的类,而不是 ExtrusionPlantMachinesMorphology,所以我不确定我是否实现了您的目标。
  • ExtrusionPlantMachinesMorphology 是该类的旧名称,它是一个复制/粘贴错误你能看到我你的测试代码吗?
  • 用完整的测试文件更新了答案。
  • 谢谢!!我解决了!我在没有其他泛型的情况下实例化了该类...例如:AbstractPlant plant = new AbstractPlant(){..};
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 2013-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多