检查数组中的元素是否是Java中的SubClass

时间:2016-04-02 20:20:15

标签: java arrays object

让我们假设我想检查Object数组中的值是否属于超类或子类,例如我的超类是Called Animal,我声明了一个类型为Animal的数组

Animal myAnimals[] = new Animal[];

现在假设有像Lion,Tiger,Elephant等动物的子类。如果我要遍历数组,我如何区分子类(Lion,Tiger等)和超类Animal?谢谢!

3 个答案:

答案 0 :(得分:6)

使用instanceof

  

在运行时,如果[...],instanceof运算符的结果为true   可以将引用(第15.16节)转换为ReferenceType而不使用   引发ClassCastException。

for (Animal a : myAnimals) {
    if (a instanceof Lion) System.out.println("Lion");
    // etc.
}

答案 1 :(得分:1)

正如@YassinHajaj已经说过你可以使用instanceof运算符:

 for (Animal animal : animals) {

     if (animal instanceof Tiger) {

           Tiger tiger = (Tiger) animal;
     }
 }

然而,这导致非结构化代码,此外这很难维护。我个人更喜欢更面向对象的方式。

正如@JBNizet在评论中建议的那样,您可以使用polymorphism。这很好但不完美:你需要改变所有动物类的实现以增加一些逻辑。

访客模式

但是,如果将其与visitor pattern结合使用。这将变得非常强大,因为您可以将逻辑分成访问者类:

interface AnimalVisitor {

    void visitLion(Lion lion);
    void visitFish(Fish fish);

    // Gets called when animal does not override the accept method:
    void visitDefault(Animal animal); 
}

class Animal {

    public void accept(AnimalVisitor visitor) {
        visitor.visitDefault(this);
    }
}

class Fish extends Animal {

    @Override
    public void accept(AnimalVisitor visitor) {
        visitor.visitFish(this);
    }
}

class Lion extends Animal {

    @Override
    public void accept(AnimalVisitor visitor) {
        visitor.visitLion(this);
    }
}

然后你可以用这样的东西轻松替换你的循环:

AnimalVisitor visitor = new AnimalVisitor() {

    @Override
    public void visitLion(Lion lion) {
        // Do something with lion
    }

    @Override
    public void visitFish(Fish fish) {
        // Do something with fish
    }
}

for (Animal animal : animals) {
    animal.accept(visitor);
}

我们甚至可以更进一步:

反思访客

由于为每种不同类型的动物添加特定的visitAnimal方法很烦人,我们可以使用reflection来避免这种情况!这将导致更小更清晰的代码:

interface Visitable { }

class Animal implements Visitable {

    // No accept method
}

class Fish extends Animal {}
class Goldfish extends Fish {}
class Shark extends Fish {}


// Take for example this visitor:

class BittenByVisitor extends ReflectiveVisitor {


    private Surfer surfer;

    public BitByVisitor(surfer) {
        this.surfer = surfer;
    }

    // We only care about the sharks:

    public void visit(Shark shark) {

        surfer.die();
    }


    // Any other fish is just the same:

    public void visit(Fish fish) {

        surface.decreaseHealthBy(1);
    }

    // It also works with interfaces:
    public void visit(VerySmallFish fish) {

        // Do nothing by purpose!
    }
}

这里是反思访客的实施:

abstract class ReflectiveVisitor {

    public void visit(Visitable v) throws NoSuchMethodException {
        Method m = findMethod(v);

        try {
            m.invoke(this, new Object[] { v });
        }

        catch ( IllegalAccessException e1 ) { /* code handling */ }
        catch ( InvocationTargetException e2 ) { /* code handling */ }
    }

    private Method findMethod(Visitable v) throws NoSuchMethodException {

        String methodName = "visit";
        Class visitable = v.getClass();

        while ( isAncestorOf("Visitable", visitable) {

            Class visitor = getClass();

            while ( isAncestorOf("Visitor", visitor) {

                try {
                    Method m = visitor.getDeclaredMethod(methodName, new Class[]{visitable});
                    return m;
                } catch ( NoSuchMethodException e ) {
                    visitor = visitor.getSuperclass();
                }
            }

            visitable = visitable.getSuperclass();
        }

        String errMsg = "put error message here";
        throw new NoSuchMethodException(errMsg);
    }

    private boolean isAncestorOf(String ancestorName, Class descendant) {

        try {
            return Class.forName(ancestorName).isAssignableFrom(descendant);
        }
        catch ( ClassNotFoundException e ) { /* code handling */ }
            return false;
        }
    }
}

源代码来自this paper

我个人喜欢使用反射访问者来避​​免Visitable课程。您可以这样定义:

class ReflectiveVisitor<T> {

    public void visit(T visitable);
}

答案 2 :(得分:1)

您可以使用instanceof ..

迭代每个元素并检查子类型