【问题标题】:extracting all instances of subclass from arraylist从arraylist中提取子类的所有实例
【发布时间】:2015-07-23 05:52:15
【问题描述】:

我有ArrayList<Unit> units。我想编写一个函数,该函数将返回指定子类的所有对象,用作参数。但是我无法让它工作。这是我所拥有的:

public static ArrayList<? extends Unit> getTheseUnits(Class<? extends Unit> specific_unit) {
    ArrayList<specific_unit> res = new ArrayList<>();  //'specific_unit' is in red here. Adding '.class' or '.getClass()' after it does not resolve anything
    for (Unit u : units){
        if (u instanceof specific_unit){
            res.add(u);
        }
    }
    return res;
}

【问题讨论】:

  • “这里是红色的”转换为编译器错误。在尝试编写此类代码之前,也许您应该真正学习一些 Java 基础知识。含义:在转向泛型类型的复杂用法之前,了解编译器错误等基本概念(以及如何阅读它们)!您的“此处的红色”归结为:您不能将变量名用作泛型类型,因此 ArrayList &lt;specific_unit&gt; 不是正确的 Java 声明。
  • @Jägermeister 我知道这是编译器错误,但是 Eclipse 仅说明 specific_unit cannot be resolved 并没有多大帮助

标签: java generics arraylist


【解决方案1】:

按类别过滤它们:

public static List<Unit> getUnitsByClass(Class<? extends Unit> specificClass, List<? extends Unit> units) {
     return units.stream()
                 .filter(e -> e.getClass().equals(specificClass))
                 .collect(Collectors.toList());
}

如果您想将此方法参数化,请使用其他选项:

public static <T extends Unit> List<T> getUnitsByClass(Class<T> specificClass, List<? extends Unit> units) {
     return (List<T>) units.stream()
                           .filter(e -> e.getClass().equals(specificClass))
                           .collect(Collectors.toList());
}

但在第二种方法中,您将收到未经检查的强制转换警告。

【讨论】:

  • 我觉得你的回答有点短。看来他对泛型完全不了解;因此他可能无法理解您的“SpecificUnit.class”不是他的“specific_unit”变量。
  • @Jägermeister OP 的 specific_unit 变量属于类型类,我将其重命名为 specificClass 以更清楚。
  • @Jägermeister 也许我一直不知道如何正确使用泛型,但我并不愚蠢。
  • 感谢@SashaSalauyou 的回答
  • @CoderinoJavarino 我不是故意侮辱你的。但你是对的;我可以/应该建议“总体上”改进答案(而不是暗示您特别可能在那里遇到问题)
【解决方案2】:

您不能在变量上使用instanceof。相反,您应该使用isInstance

只需替换这一行:

if (u instanceof specific_unit) {

if (specific_unit.isInstance(u)){

【讨论】:

  • 为了完整起见:他的方法仍然无法编译,因为他在创建“返回值”数组列表时也使用了 specific_unit 作为类型参数。您可能也想更新关于这方面的答案。
【解决方案3】:

如果你改变你的方法签名它可以工作:

public static <T extends Unit> ArrayList<T> getTheseUnits(Class<T> specific_unit) {
    ArrayList<T> res = new ArrayList<>();
    for (Unit u : units){
        if (specific_unit.isAssignableFrom(u.getClass()) {
            res.add(u);
        }
    }
    return res;
}

只需为您的泛型 (&lt;T&gt;) 使用特定类型,而不是通配符 (?)。这是创建您的返回类型 (ArrayList&lt;T&gt;) 所必需的。

您还应该使用isAssignableFrom() 而不是instanceof。请注意,isAssignableFrom() 也会检查子类型。

请再次检查此代码,因为我没有测试它。

【讨论】:

  • 为什么在类型不相关的情况下使用“T”;因此“?”会做吗?
  • @Jägermeister 需要T 类型来定义新的ArrayList(问题中的编译器错误)。
【解决方案4】:

试试这个:

public static <T extends Unit> ArrayList<T> getTheseUnits(Class<T> specific_unit) {
    ArrayList<T> res = new ArrayList<T>();
    for (Unit u : units){
        if (specific_unit.isInstance(u)){
            res.add((T) u);
        }
    }
    return res;
}

【讨论】:

    【解决方案5】:

    也许您可以尝试在声明和返回中不使用类而是接口(因此使用 List 而不是 ArrayList 和 Unit 而不是 SpecificUnit)。我已将类和实例重命名为 java 样式...例如:

    public static List<? extends Unit> getTheseUnits(Class<? extends Unit> specificUnit, List<Unit> units) {
        List<Unit> res = new ArrayList<Unit>();
        for (Unit u : units){
            if (specificUnit.isInstance(u)){
                res.add(u);
            }
        }
        return res;
    }
    

    编译。可能这就是您正在寻找的...如果有用请告诉我

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-08-23
      • 2013-10-31
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 2018-05-13
      相关资源
      最近更新 更多