How to determine an object's class?
如果类B和类C扩展类A并且我有一个类型为B或C的对象,我如何确定它是哪个类型的实例?
- @首先想到的是星空投射。如果不需要操作符的话,我怀疑它是否存在。
1 2 3
| if (obj instanceof C) {
//your code
} |
- 注意反向检查或如何检查对象是否不是类的实例是很有用的:if(!(obj instanceof C))。
- 我相信getClass()方法是原始问题的答案。在这种情况下(obj instanceof a)也会给出"true"输出,但目的是在图片中找到对象的运行时类。如果parent1由child1和child2扩展,请尝试以下方法:codechild1 child1=new child1();parent1 parentchild=new child2();child2 child2=new child2();(child1 instanceof parent1);(child1 instanceof child1);(parentchild instanceof child2);(parentchild instanceof parent1);(parentchild instanceof child1);codeit可以清除instanceof的意图。
- 绝对是构建接口的替代方案
- 如果我有两个实现单个接口的类呢?如何区分对象的确切类?
- 但有一点,如果obj为空,它就不起作用。然后解决方案将是ParentInterface.Class.IsassignableFrom(Child.Class)
- 想象一下,如果您有B、C、D、E等,解决方案会变得非常冗长。模式匹配更好,但仍处于建议状态。
使用object.getClass()。它返回对象的运行时类型。
提出了多种正确的答案,但仍有更多的方法:Class.isAssignableFrom()和简单地尝试投射物体(可能会抛出ClassCastException)。
总结可能的方法
让我们总结一下测试对象obj是否是C类型的实例的可能方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| // 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处理方式不同:
- 在前2种方法中,如果obj是null(null不是任何事物的实例),则表达式对false进行评估。
- 第三种方法显然会抛出一个NullPointerException。
- 相反,第4和第5种方法接受null,因为null可以强制转换为任何类型!
To remember: null is not an instance of any type but it can be cast to any type.
号笔记
- Class.getName()不应用于执行"is instance of"测试,因为如果对象不是C类型,而是它的一个子类,它可能具有完全不同的名称和包(因此类名显然不匹配),但它仍然是C类型。
- 由于同样的继承原因,Class.isAssignableFrom()不对称:如果obj的类型是C的一个子类,obj.getClass().isAssignableFrom(C.class)将返回false。
- 这是对不同方法中许多陷阱的一个非常好的总结。谢谢你这么一篇完整的文章!
您可以使用:
1 2 3
| Object instance = new SomeClass ();
instance. getClass(). getName(); //will return the name (as String) (=="SomeClass")
instance. getClass(); //will return the SomeClass' Class object |
号
Hth.但我认为在大多数情况下,将其用于控制流程或类似的事情并不是一个好的实践。
- 我使用它来创建通用记录器,所以我将对象发送到记录器,它根据对象的类名记录,而不是每次都给出日志标记或日志字符串。谢谢您
使用任何建议的方法都被认为是基于糟糕的OO设计的代码味道。
如果你的设计很好,你不应该发现自己需要使用getClass()或instanceof。
任何建议的方法都可以,但只是记住一些设计方面的问题。
- 是的,使用多态方法调用可以避免使用getClass和instanceOf的99%。
- 我同意。在本例中,我正在处理由XML生成的对象,这些对象遵循的是一个设计糟糕的模式,我不拥有该模式的所有权。
- 在这些情况下,通常都是这样,遗留代码、不属于您的糟糕设计等等……
- 当然不是。有时界面分离是好的。有时您想知道A是否为B,但不想强制要求A为B,因为大多数功能只需要A—B具有可选功能。
- 此外,有时需要确保对象与所比较的类相同;例如,当我创建自己的类时,我喜欢重写对象的equals方法。我总是验证进入的对象是否属于同一类。
- 另外,我会说,告诉人们一些不好的事情,而不解释原因,也不参考论文、书籍或任何其他解释问题的资源被认为是不具有建设性的。因此,我知道我在StackOverflow,我不知道为什么人们如此反对这个答案。这里有些变化…
- 一些任务,比如序列化,获取类型,也许是最简单的方法?
- 还有其他一些情况,特别是在讨论DI或生产者框架时,了解类类型对于绑定是必要的。
- 在我的例子中,我同意@adri&np&;rez-cuz,使用getClass处理一个对象,从而避免了每次开发人员初始化API类时手工给出名称的开销。为了实现OO和节省代码的冗余重复,我需要使用object.getClass().getSimpleName(),这是一个例子,我认为还有很多地方需要instanceof来实现函数的通用性和遵循OO原则…
- 在理论上,理论和实践没有区别;在实践中,有区别。OO理论是好的,但当面对现实世界时,事情会变得丑陋。
- 我知道我在这里有点晚了,但是我明白你的观点,那就是它不应该是必要的,尽管最近我遇到了一个实际需要它的情况,而这个情况是在对象的equals方法的覆盖中。我需要在hashmap中创建一个符合等式的特殊情况,但是通常的equals方法不起作用。也许有更好的方法可以做到这一点,但是函数的实例确实有帮助。
在这种情况下我们可以使用反射
1
| objectName.getClass().getName(); |
。
示例:
1 2 3 4
| protected void doGet (HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException {
String name = request. getClass(). getName();
} |
在这种情况下,您将获得对象传递给HttpServletRequest接口引用变量的类的名称。
- 这是正确的。仅使用obj.getClass()将返回类名,前缀为单词class的x。
- request.getClass().getName();打印所有包裹!以及类名
在"Class类上还有一个.isInstance方法。如果你通过myBanana.getClass()得到一个对象的类,你可以看到你的对象myApple是否与myBanana是同一类的实例,通过
1
| myBanana.getClass().isInstance(myApple) |