2009-11-02 47 views
1

我想知道如何在java中运行时识别子类。在我的程序中,我调用了一个返回超类对象的方法。该对象可以是其任何一个子类的实例。我想知道该对象是运行时哪个子类的实例,以便我可以将其转换为该子类并访问子类方法。任何人都可以帮助我吗?在对象上在运行时识别子类

感谢

+0

谢谢..现在我知道该怎么做了,Iam试图改变设计以避免这种编码 – daniel 2009-11-02 09:34:27

回答

4

调用getClass()的访问类的对象,告诉您该对象的实际类型。然后,您可以将它与任何类的“.class”静态成员进行比较。

if (obj.getClass().equals(Foo.class)) { ... } 

然而,很多人会说你的建议是坏设计。确保它是必要的,并考虑替代品。在实现像equals()这样的方法时通常是必需的。

+2

我认为instanceof是一种更好的方法,但是您得到我的投票指出这确实表明设计是错误的。 – Dustin 2009-11-02 06:51:40

+0

通过equals()比较Class对象没有意义。这可以替换为简单的==。 – 2009-11-02 10:10:14

+0

考虑到问题陈述,我不同意instanceof是解决方案。他有兴趣根据对象的确切类别采取行动,而instanceof并没有完全捕捉到这种情况:只要参数与给定的类是分配兼容的,而不是仅仅是一个实例,情况就是如此。在某些情况下,这是等同的,但不是全部。 – 2009-11-02 17:43:16

0

您可以使用instanceof运算符来测试对象的类型,然后进行转换。

1

使用instanceof运算符。像这样

Superclass aSup = ...; 
if(aSup instanceof Subclass) { 
    Subclass aSub = (Subclass) aSup; 
    aSub.subclass_method(...); 
} 
7

您可以使用instanceof来检查对象是否是特定类的实例。例如:

if (animal instanceof Cat) { 
    Cat cat = (Cat) animal; 
    cat.meow(); 
} else if (animal instanceof Dog) { 
    Dog dog = (Dog) animal; 
    dog.bark(); 
} 

但是,过度使用instanceof(或向下转换,就此而言)通常被认为是设计不佳的标志。反而利用多态性更好。例如,在Animal中有一个(可能是抽象的)“speak”方法,然后每个子类都有不同的实现。上面的代码将被用电话代替说话了:

animal.speak(); 
+0

+1,用于解释使用'instanceof'是不良设计的一个症状。 – Jesper 2009-11-02 10:22:11

1

注意,如果对象是一个类型分配给指定的 类的instanceof是真实的。以下(如上所述)将工作

if (o instanceof Cat.class) { 
    // .. 
} else if (o instanceof Dog.class) { 
    // .. 
} else { 
    throw IllegalArgumentException("Unexpected type"); 
} 

但是,如果你引入一个新的猫的子类,例如虎然后 第一个子句将被触发,除非你更新了所有代码 这样做。

您可能想要搜索双重调度 必须做到上述,当然不知道你的问题 试图解决这个可能不适用。

1

您可以像上面提到的那样使用'instanceof'操作符和直接的Class对象比较。

但是,如果你想修改代码以避免明确的检查,我看到两条路走:


interface Handler<T> { 
    void handle(T object); 
} 

Map<Class<?>, Handler<?>> HANDLERS = /* init handlers mappings */; 

... 

public void process(Object obj) { 
    Handler<?> handler = HANDLERS.get(obj.getClass()); 
    if (handler == null) { 
     throw new IllegalStateException("bla-bla-bla, no handler is registered for class " + obj.getClass()); 
    } 
    handler.handle(obj); 
}