检查对象是不是是类的实例(但不是其子类的实例)
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 的实例)?那就是:
是否有类似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 个类 Foo
和 SuperFoo
并让 Bar
从 SuperFoo
下降可能是一种捏造它的方法,但代码会变得更加复杂正因为如此。所以它可能更面向对象,但我不确定它是否更好。
是的,我很欣赏这个答案,但在 SO 你真的需要避免假设 why OP 询问并暗示他们做错了什么。有很多有效案例可以满足这种需求。【参考方案2】:
如果您正在寻找完全匹配的类,唯一的方法是qux.getClass().equals(Foo.class)
。 instanceof 也将为子类返回 true。
【讨论】:
【参考方案3】:你应该使用instanceof
if(qux instanceof Foo && !(qux instanceof Bar))
...
这适用于类和接口,因此在大多数情况下,它应该优先于不适用于接口的.class
。
【讨论】:
这不会捕捉到Baz
是Foo
的子类的情况。
是这样吗?对于 Bar
的实例,&&
的 rhs 应该返回 false,无论它扩展了哪些其他类
假设Baz
是Foo
的直接子类。然后,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)
以防止它来自 NullPointerException
。
instanceof
运算符判断一个对象是一个类的实例还是它的父类(直到任何级别)。
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 检查。
【讨论】:
以上是关于检查对象是不是是类的实例(但不是其子类的实例)的主要内容,如果未能解决你的问题,请参考以下文章