如何确定对象的类?


510

如果class B和class C扩展了class A并且我有一个对象类型BC,那么如何确定它是实例的哪种类型?


14
@starblue Casting将是我想到的第一件事。我怀疑如果没有任何需要,instanceof运算符会存在。
b1nary.atr0phy 2012年

@ b1nary.atr0phy最好先使用nottanceof运算符。如果有强制转换为不兼容的类型,我相信,这将导致一个ClassCastException
committedandroider

Answers:


801
if (obj instanceof C) {
//your code
}

31
注意反向检查或如何检查对象是否不是类的实例非常有用:if(!(obj instanceof C))
Dzhuneyt 2012年

32
我相信getClass()方法是原始问题的答案。在这种情况下(obj instanceof A)也将给出“ true”输出,但目的是在图片中找到对象的运行时类。如果Parent1由Child1和Child2扩展,请尝试以下Child1 child1 code = new Child1(); Parent1 parentChild = new Child2(); Child2 child2 = new Child2(); (Parent1的child1实例);(child1的child1实例);(parentChild instanceof Child2); (Parent1的parentChild实例);(parentChild instanceof Child1); code ,这可能会清除instanceof的意图。
Bhavesh Agarwal

绝对可以替代构建接口
JohnMerlino 2014年

3
如果我有两个实现单个接口的类怎么办?如何区分对象的确切类别?
olyv 2015年

3
不过有一件事,如果obj为null则不起作用。然后,解决方案将是ParentInterface.class.isAssignableFrom(Child.class)
alexbt


178

提出了多个正确答案,但还有更多方法:Class.isAssignableFrom()并且仅尝试投射对象(可能会抛出ClassCastException)。

可能的方法总结

让我们总结一下测试对象obj是否为type实例的可能方法C

// Method #1
if (obj instanceof C)
    ;

// Method #2
if (C.class.isInstance(obj))
    ;

// Method #3
if (C.class.isAssignableFrom(obj.getClass()))
    ;

// Method #4
try {
    C c = (C) obj;
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

// Method #5
try {
    C c = C.class.cast(obj);
    // No exception: obj is of type C or IT MIGHT BE NULL!
} catch (ClassCastException e) {
}

null处理上的差异

null但是在处理方面有所不同:

  • 在前两种方法中,表达式的计算结果为falseif objis nullnull不是任何实例)。
  • 第三种方法NullPointerException显然会抛出一个错误。
  • 相反,第4和第5种方法可以接受,null因为null可以转换为任何类型!

要记住:null 不是任何类型的实例,但是可以将其强制转换为任何类型。

笔记

  • Class.getName()如果对象不是类型而是它的子类,则不应用于执行“ is-instance-of”测试C,它可能具有完全不同的名称和包(因此,类名显然不匹配),但是仍然类型C
  • 出于相同的继承原因,Class.isAssignableFrom()它不是对称的:如果类型为的子类,
    obj.getClass().isAssignableFrom(C.class)则将返回。falseobjC

6
这是对使用不同方法的许多陷阱的一个很好的总结。感谢您完成如此完整的撰写!
凯尔辛2015年

32

您可以使用:

Object instance = new SomeClass();
instance.getClass().getName(); //will return the name (as String) (== "SomeClass")
instance.getClass(); //will return the SomeClass' Class object

HTH。但是我认为在大多数情况下,将其用于控制​​流或类似的东西并不是一种好习惯。


我用它来创建通用记录器,因此我将对象发送到记录器,它根据对象的类名进行记录,而不是每次都给出日志标记或日志字符串。谢谢
MBH

24

所建议使用的任何方法的任何使用均被视为基于不良OO设计的代码气味。

如果您的设计不错,则不应发现自己需要使用getClass()instanceof

任何建议的方法都可以使用,但是在设计方面要记住一些事情。


3
是的,通过多态方法调用,可以避免使用getClass和instanceof的99%。
比尔蜥蜴

3
我同意。在这种情况下,我使用的是从xml生成的对象,这些对象遵循设计欠佳的模式(我没有所有权)。
航空母舰

28
没必要。有时接口分离是好的。有时您想知道A是否为B,但您并不想强制A为B,因为大多数功能只需要A-B具有可选功能。
MetroidFan2002

8
另外,有时需要确保对象与您要比较的对象属于同一类。例如,当我创建自己的类时,我想覆盖Object的equals方法。我总是验证进入的对象是同一类。
StackOverflowed 2012年

58
另外,我想说的是,告诉人们某些事情是不好的,而没有确切解释为什么或没有提到解释问题的论文,书籍或任何其他资源,都被认为没有建设性。因此,知道我在StackOverflow中后,我不知道为什么人们对这个答案的评价如此之高。事情正在改变这里...
阿德里安·佩雷斯

15

在这种情况下,我们可以使用反射

objectName.getClass().getName();

例:-

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    String name = request.getClass().getName();
}

在这种情况下,您将获得该对象传递给HttpServletRequest接口引用变量的类的名称。


这是对的。仅使用obj.getClass()会返回className,prefixex并带有单词class
x6iae 16'7

request.getClass().getName();打印所有包装!以及班级名称
shareef


1

isinstance()如果您想在运行时知道,进行检查是不够的。采用:

if(someObject.getClass().equals(C.class){
    // do something
}

0

我在GeneralUtils类中使用打击功能,检查它是否有用

    public String getFieldType(Object o) {
    if (o == null) {
        return "Unable to identify the class name";
    }
    return o.getClass().getName();
}

0

我使用Java 8泛型在运行时获取对象实例,而不必使用切换用例

 public <T> void print(T data) {
    System.out.println(data.getClass().getName()+" => The data is " + data);
}

传递任何类型的数据,该方法将打印您在调用时传递的数据类型。例如

    String str = "Hello World";
    int number = 10;
    double decimal = 10.0;
    float f = 10F;
    long l = 10L;
    List list = new ArrayList();
    print(str);
    print(number);
    print(decimal);
    print(f);
    print(l);
    print(list);

以下是输出

java.lang.String => The data is Hello World
java.lang.Integer => The data is 10
java.lang.Double => The data is 10.0
java.lang.Float => The data is 10.0
java.lang.Long => The data is 10
java.util.ArrayList => The data is []
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.