从ArrayList提取所有子类实例

5

我有一个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 <specific_unit>不是正确的Java声明。 - GhostCat
@Jägermeister 我知道这是编译器错误,但是Eclipse只是简单地指出specific_unit cannot be resolved并没有提供太多帮助。 - Coderino Javarino
5个回答

4

按类过滤:

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”变量是不同的东西。 - GhostCat
@Jägermeister OP的specific_unit变量是一个类的类型,我将其重命名为specificClass以使其更清晰明了。 - Alex Salauyou
@Jägermeister 或许我不知道如何始终正确地使用泛型,但我并不愚笨。 - Coderino Javarino
1
感谢 @SashaSalauyou 的回答。 - Coderino Javarino
@CoderinoJavarino,我并不是想侮辱你。但你说得对;我本可以/应该建议“一般性地”改进答案(而不是暗示你可能在那方面有问题)。 - GhostCat
@Jägermeister,我对我的答案进行了一些改进,如果你有什么要补充的,请随意评论/编辑。 - Alex Salauyou

4

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

只需替换此行:

if (u instanceof specific_unit) {

使用

if (specific_unit.isInstance(u)){

仅供完整性:他的方法仍无法编译,因为在创建“返回值”arraylist时,他也使用了specific_unit作为类型参数。您可能还想就该方面更新您的答案。 - GhostCat

2
如果您更改方法签名,它就可以工作:
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;
}

只需使用特定类型而非通配符类型(?)来定义泛型(<T>),就能创建返回类型(ArrayList<T>)。

另外,应该使用isAssignableFrom()代替instanceof。请注意,isAssignableFrom()还会检查子类型。

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


为什么在类型无关的情况下使用“T”;因此,“?”就可以了? - GhostCat
@Jägermeister 需要定义一个新的 ArrayList 类型 T(问题中的编译器错误)。 - Uwe Plonus

1

try this:

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;
}

0

也许你可以尝试在声明和返回时不使用类而是接口(因此使用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;
}

编译通过。很可能这就是你要找的...如果有用,请告诉我。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接