instanceof关键字用法

时间:2011-07-06 18:22:03

标签: java instanceof

使用instanceof关键字反对object oriented programming的本质? 我的意思是这是一个糟糕的编程习惯吗? 我在某处读到使用instanceof关键字意味着设计可能不那么好。有没有更好的解决方法?

8 个答案:

答案 0 :(得分:14)

一般来说是的。最好保留所有依赖于该类中特定类的代码,并且使用instanceof通常意味着您已将某些代码放在该类之外。

看看这个非常简单的例子:

public class Animal
{
}

public class Dog extends Animal
{
}

public class Cat extends Animal
{
}

public class SomeOtherClass
{
  public abstract String speak(Animal a)
  {
    String word = "";

    if (a instanceof Dog)
    {
      word = "woof";
    }
    else if (a instanceof Cat)
    {
      word = "miaow";
    }

    return word;
  }
}

理想情况下,我们希望所有针对狗的行为都包含在Dog类中,而不是传播到我们的程序中。我们可以通过重写我们的程序来改变它:

public abstract class Animal
{
  public String speak();
}

public class Dog extends Animal
{
  public String speak()
  {
    return "woof";
  }
}

public class Cat extends Animal
{
  public String speak()
  {
    return "miaow";
  }
}

public class SomeOtherClass
{
  public String speak(Animal a)
  {
    return a.speak();
  }
}

我们已指定Animal必须使用speak方法。现在SomeOtherClass不需要知道每种动物的具体细节 - 它可以将其移交给Animal的子类。

答案 1 :(得分:4)

推广虚拟方法有许多好的答案,但instanceof也有其用途。想象一下,您迭代List<Event>,以获取所有Urgent个对象。你可以使用isUrgent()来做,但我不确定它是否必须更简洁或可读。此外,isUrgent()要求Event知道其子类可能拥有相应的属性,这可能是:

  • 被视为违反模块化原则的东西;
  • 如果Event属于某个无法修改的库,则
  • 甚至不可能。
  • 答案 2 :(得分:3)

    支持多态和动态绑定到向下转换和instanceof。这是“OO Way”,使您能够编写不需要了解子类型的代码。

    示例

    abstract class Animal {
        public abstract void talk();
        //...
    }
    
    class Dog extends Animal {
        public void talk() {
            System.out.println("Woof!");
        }
        //...
    }
    
    class Cat extends Animal {
        public void talk() {
            System.out.println("Meow!");
        }
        //...
    }
    
    class Hippopotamus extends Animal {
        public void talk() {
            System.out.println("Roar!");
        }
        //...
    }
    
    class Main {
    
        public static void main(String[] args) {
    
            makeItTalk(new Cat());
            makeItTalk(new Dog());
            makeItTalk(new Hippopotamus());
        }
    
        public static void makeItTalk(Animal animal) {
    
            animal.talk();
        }
    }
    

    答案 3 :(得分:3)

    当通过虚拟方法实现相同的效果时,不鼓励使用instanceof,例如thomson_matt。 但是,在某些情况下有必要使用instanceof。例如,当您的代码从外部源获取Object时,例如,返回Object的网络或第三方API,您必须确定此Object的类型并采取相应的行动。

    答案 4 :(得分:3)

    关键是不要将instanceof视为常见“常规练习”的一部分。与一般的内省一样,instanceof是一种特殊的工具,特别适用于非典型情况。每当你使用'instanceof'时,你也可能会发现自己正在使用平台的其他“特殊”部分,例如更常见的反射。

    只要你发现自己使用它,你就会接受你所做的事情,如果没有更优雅/实用的替代方案,你所做的就是一件好事,那就没关系了。

    尽管如此,日常计划中最典型的情况可能是:

    • 实施equals()
    • 阅读序列化对象
    • 在其他一些情况下,您会获得一个数组/项目集合,例如:枚举框架/容器中的JComponents,然后根据类型采取行动。

    您可以尝试并坚持的经验法则是不要求库的用户必须使用'instanceof',而是在库内部具有“instanceof”的任何情况。

    或者换句话说,你应该重新构建你的问题:“'intsanceof'是 的解决方法是什么?”

    答案 5 :(得分:2)

    这是不鼓励的,因为人们可能会用它来做这样的事情:

    if( myAnimal instanceof Dog )
        ((Dog)myAnimal).bark();
    else( myAnimal instanceof Cat )
        ((Cat)myAnimal).meow();
    

    相反,Animal应该有一个speak()方法DogCat继承。在具有多态性和动态绑定的适当OOP中,您只需执行

    myAnimal.speak();
    

    但是,在某些情况下,您必须使用instanceof来确定对象的特定类型。也许你家里有一个Animals的列表,walk()中你唯一想要的是Dog。在这种情况下,您将遍历您的列表并且只会walk()狗。

    答案 6 :(得分:0)

    创建工厂的情况如何(见下文)? 在这种情况下,我不认为Animal子类知道如何为自己构建一个笼子是合适的。它似乎超出了Animal的范围,并迫使Animal子类采取不是Animal所固有的行为。

    public static Cage createCage(Animal animal) {
      if (animal instanceof Dog)
        return new DogHouse();
      else if (animal instanceof Lion)
        return new SteelCage();
      else if (animal instanceof Chicken)
        return new ChickenWiredCage();
      else if (animal instanceof AlienPreditor)
        return new ForceFieldCage();
      ...
      else
        return new GenericCage();
    }
    

    答案 7 :(得分:0)

    instaceOf操作的另一种用法可能是错误处理。如果您对异常有类似的错误处理,并且您希望将它们全部放在一个地方,则可以使用:

    public void handleError(Throwable t, HttpServletRequest req) {
       if (t instaceOf ValidationException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else {
                  ...doSomewthing......
       }
    
    }
    

    使用上面的代码,你可以避免有很多

    } catch <Exception> {
    

    阻止而只有一个

    } catch (Throwable t) {
       handleError(t, request);
       return "errorPage" or whateveryouwant;
    }
    

    另外,还有一件事是,你检查java源代码,你会发现很多用法的用法..

    一个好的链接: article about usage of instaceof