检查对象是不是是类的实例(但不是其子类的实例)

Posted

技术标签:

【中文标题】检查对象是不是是类的实例(但不是其子类的实例)【英文标题】: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 时)是错误的应用程序设计 【参考方案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

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

重要提示-:

    instanceof 运算符不会抛出 NullPointerException 异常,以防引用变量未指向任何对象(即它具有空引用)。 car.getClass().equals(Car.class) 将抛出 NullPointerException 异常,以防car 未指向任何对象(即它具有空引用)。因此,必须对此进行额外的空检查,例如 car != null && car.getClass().equals(Car.class) 以防止它来自 NullPointerExceptioninstanceof 运算符判断一个对象是一个类的实例还是它的父类(直到任何级别)。 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 检查。

【讨论】:

以上是关于检查对象是不是是类的实例(但不是其子类的实例)的主要内容,如果未能解决你的问题,请参考以下文章

Python 检查类的实例

Python检查类的实例

python元类深入解析

抽象方法真的不能实例化么?

如何检查对象是不是是新型用户定义类的实例?

Python——检查对象是不是是某个模块中任何类的实例