【问题标题】:Check if an object is an instance of a class (but not an instance of its subclass)检查对象是否是类的实例(但不是其子类的实例)
【发布时间】:2013-05-17 07:42:28
【问题描述】:

对于这个例子:

public class Foo{}

public class Bar extends Foo{}

....

void myMethod(Foo qux){
   if (checkInstance(qux,Foo.class)){
     ....
   }
}

如何检查qux 是否是 Foo 的实例(但不是其子类 foo 的实例)?那就是:

  • checkInstance(qux,Foo.class)=true
  • checkInstance(qux,Bar.class)=false

是否有类似instanceof 的声明用于此检查?或者我应该使用qux.getClass().equals(Foo.class)

【问题讨论】:

  • 希望对你有帮助java-samples.com/showtutorial.php?tutorialid=332你可以使用qux instanceof Foo
  • @Selvin 使用 instanceof 并不一定意味着应用程序设计错误。例如,当您尝试将数据映射到多种视图类型时,它会在适配器中使用。
  • 但是检查对象是否是 Foo 的实例而不是 Bar(当 Bar 扩展 Foo 时)是错误的应用程序设计

标签: java instanceof


【解决方案1】:

如果您必须这样做,唯一的方法就是您建议的 getClass().equals(Foo.class) 选项。

然而,OO 设计的目标是让您以同样的方式对待任何 Foo。实例是否是子类在普通程序中应该是无关紧要的。

【讨论】:

  • 我认为很多堆栈交换问题都与不正常的情况有关。
  • @WarrenDew 我同意。但很大一部分人是在寻求一种方法来实施他们自己的问题解决方案,而也许存在更好的解决方案。当您发现自己在 OO 语言中违反了 OO 原则时,这很好地表明您已经偏离轨道了。
  • 我不明白符合 OO 原则的更好的选择是什么
  • hmm,我猜想将Foo 分成 2 个类 FooSuperFoo 并让 BarSuperFoo 下降可能是一种捏造它的方法,但代码会变得更加复杂正因为如此。所以它可能更面向对象,但我不确定它是否更好。
  • 是的,我很欣赏这个答案,但在 SO 你真的需要避免假设 why OP 询问并暗示他们做错了什么。有很多有效案例可以满足这种需求。
【解决方案2】:

如果您正在寻找完全匹配的类,唯一的方法是qux.getClass().equals(Foo.class)。 instanceof 也将为子类返回 true。

【讨论】:

    【解决方案3】:

    你应该使用instanceof

    if(qux instanceof Foo && !(qux instanceof Bar)) {
        ...
    }
    

    这适用于类和接口,因此在大多数情况下,它应该优先于不适用于接口的.class

    【讨论】:

    • 这不会捕捉到BazFoo 的子类的情况。
    • 是这样吗?对于 Bar 的实例,&& 的 rhs 应该返回 false,无论它扩展了哪些其他类
    • 假设BazFoo 的直接子类。然后,if 子句的两边都将评估为 true
    • 你看到!,对吗?
    • 是的,我愿意。在我的示例中,Baz 不是Bar 的实例。请注意,我稍微扩展了 OP 的原始示例以讨论一般情况。
    【解决方案4】:

    我刚刚尝试了以下代码,它似乎工作正常

    public class BaseClass {
    
        private String a;
    
        public boolean isInstanceOf(BaseClass base){
            if(base == null){
                return false;
            }
            else if(getClass() == base.getClass()){
                return true;
            }else{
                return false;
            }
        }
    
    }
    
    
    
    public class DervidClass extends BaseClass {
    
    
        public boolean isInstanceOf(DervidClass base) {
            if(base == null){
                return false;
            }
            else if(getClass() == base.getClass()){
                return true;
            }else{
                return false;
            }
        }
    
    
    }
    
    public class myTest {
    public static void main(String[] args) throws ParseException {
    
    
            BaseClass base = new BaseClass();
            BaseClass base1 = new BaseClass();
            DervidClass derived = new DervidClass();
    
            BaseClass d1 = new DervidClass();
    
            System.out.println(base.isInstanceOf(d1));
            System.out.println(d1.isInstanceOf(d1));
            System.out.println((d1 instanceof BaseClass));
    
    
        }
    

    【讨论】:

      【解决方案5】:

      我已经阅读了迄今为止发布的所有答案,但还没有找到满意的答案。回答是否有类似instanceof 这样的声明用于此检查?或者我应该使用qux.getClass().equals(Foo.class) 问题我会说是的,java 中有instanceof 运算符来检查对象是否是类的实例。下面是一个例子-:

      class Vehicle {
      
      }
      
      class Car extends Vehicle {
      
      }
      
      public class Research {
          public static void main(String[] args) {
              Vehicle vehicle = new Vehicle();
      
              if (vehicle instanceof Vehicle) {
                  System.out.println("vehicle instanceof Vehicle : TRUE");
              } else {
                  System.out.println("vehicle instanceof Vehicle : FALSE");
              }
      
              if (vehicle instanceof Car) {
                  System.out.println("vehicle instanceof Car : TRUE");
              } else {
                  System.out.println("vehicle instanceof Car : FALSE");
              }
      
              System.out.println();
              Car car = new Car();
      
              if (car instanceof Vehicle) {
                  System.out.println("car instanceof Vehicle : TRUE");
              } else {
                  System.out.println("car instanceof Vehicle : FALSE");
              }
      
              if (car instanceof Car) {
                  System.out.println("car instanceof Car : TRUE");
              } else {
                  System.out.println("car instanceof Car : FALSE");
              }
          }
      }
      

      输出-:

      vehicle instanceof Vehicle : TRUE
      vehicle instanceof Car : FALSE
      
      car instanceof Vehicle : TRUE
      car instanceof Car : TRUE
      

      Description-:instanceof 运算符告诉对象是一个类的实例还是它的父类(直到任何级别)。
      vehicle instanceof Car : FALSE 输出行表明instanceof 运算符不会判断对象是否是其子类的实例。

      另一种方法是使用getClass().equals(Foo.class) 来确定对象是否是类的实例。让我们看看下面的例子-:

      class Vehicle {
      
      }
      
      class Car extends Vehicle {
      
      }
      
      public class Research {
          public static void main(String[] args) {
              Vehicle vehicle = new Vehicle();
      
              if (vehicle.getClass().equals(Vehicle.class)) {
                  System.out.println("vehicle instanceof Vehicle : TRUE");
              } else {
                  System.out.println("vehicle instanceof Vehicle : FALSE");
              }
      
              if (vehicle.getClass().equals(Car.class)) {
                  System.out.println("vehicle instanceof Car : TRUE");
              } else {
                  System.out.println("vehicle instanceof Car : FALSE");
              }
      
              System.out.println();
              Car car = new Car();
      
              if (car.getClass().equals(Vehicle.class)) {
                  System.out.println("car instanceof Vehicle : TRUE");
              } else {
                  System.out.println("car instanceof Vehicle : FALSE");
              }
      
              if (car.getClass().equals(Car.class)) {
                  System.out.println("car instanceof Car : TRUE");
              } else {
                  System.out.println("car instanceof Car : FALSE");
              }
      
      
          }
      }
      

      输出-:

      vehicle instanceof Vehicle : TRUE
      vehicle instanceof Car : FALSE
      
      car instanceof Vehicle : FALSE
      car instanceof Car : TRUE
      

      说明-:从上面的例子可以清楚地看出,应该在哪里选择哪一个(以上两个)?

      重要提示-:

      1. instanceof 运算符不会抛出 NullPointerException 异常,以防引用变量未指向任何对象(即它具有空引用)。
      2. car.getClass().equals(Car.class) 将抛出 NullPointerException 异常,以防car 未指向任何对象(即它具有空引用)。因此,必须对此进行额外的空检查,例如 car != null && car.getClass().equals(Car.class) 以防止它来自 NullPointerException
      3. instanceof 运算符判断一个对象是一个类的实例还是它的父类(直到任何级别)。
      4. car.getClass().equals(Car.class) 将判断一个对象是否只是类的一个实例。 (根本不考虑父类和子类)

      【讨论】:

        【解决方案6】:
            package com.instance;
        
            public class Foo {
                public void instance(Foo f) {
                    System.out.println("---------");
                    System.out.println(f.getClass());
                    System.out.println(getClass());
                    if (f.getClass() == getClass()) {
                        System.out.println("Yes");
                    } else {
                        System.out.println("No");
                    }
                }
            }
        
        
        package com.instance;
        
        public class Main {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
                Foo f1 = new Foo();
                Foo f2 = new Foo();
                Foo f3 = new Bar();
                f1.instance(f1);
                f1.instance(f2);
                f1.instance(f3);
            }
        
        }
        

        【讨论】:

        • 一张图片可能会画出一千个单词,但一大块代码肯定会给出一个丑陋的答案。
        【解决方案7】:

        你已经知道 qux 是 instanceof Foo(除非它是 null...),所以你只需要一个简单的 qux instanceof Bar 和一个 null 检查。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-02-03
          • 1970-01-01
          • 2019-01-08
          • 1970-01-01
          • 2021-11-20
          • 2016-07-07
          相关资源
          最近更新 更多