【问题标题】:How to determine an object's class?如何确定对象的类别?
【发布时间】:2010-10-07 04:55:28
【问题描述】:

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

【问题讨论】:

  • @starblue Casting 将是首先想到的。如果不需要 instanceof 运算符,我怀疑它是否存在。
  • @b1nary.atr0phy 最好先使用 isnttanceof 运算符。如果强制转换为不兼容的类型,我相信这将导致 ClassCastException

标签: java inheritance


【解决方案1】:
if (obj instanceof C) {
//your code
}

【讨论】:

  • 注意反向检查或如何检查对象是否不是类的实例很有用:if(!(obj instanceof C))
  • 我相信 getClass() 方法是原始问题的答案。在这种情况下(obj instanceof A)也会给出“真实”输出,但目的是找到图片中对象的运行时类。如果 Parent1 被 Child1 和 Child2 扩展,请尝试以下code Child1 child1 = new Child1(); Parent1 parentChild = new Child2(); Child2 child2 = new Child2(); (父 1 的子 1 实例); (child1 instanceof Child1); (parentChild instanceof Child2); (Parent1 的父子实例); (parentChild instanceof Child1); code ,可以清除instanceof的意图。
  • 绝对是构建界面的替代方案
  • 如果我有两个类实现单个接口怎么办?如何区分对象的确切类别?
  • 有一点,如果 obj 为空,它就不起作用。解决方案将是 ParentInterface.class.isAssignableFrom(Child.class)
【解决方案2】:

使用Object.getClass()。它返回对象的运行时类型。

【讨论】:

  • 这实际上是你如何确定一个对象的类
  • 完美答案@Bill
  • 不知道为什么这不是最受欢迎的答案
【解决方案3】:

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

可能的方法总结

让我们总结一下测试对象obj是否是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 的处理方式有所不同:

  • 在前 2 个方法中,如果 objnullnull 不是任何实例),则表达式计算为 false
  • 第三种方法显然会抛出NullPointerException
  • 相反,第 4 和第 5 方法接受 null,因为 null 可以转换为任何类型!

记住:null不是任何类型的实例,但它可以转换为任何类型。

注意事项

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

【讨论】:

  • 这是对不同方法中许多陷阱的非常好的总结。感谢您写得如此完整!
【解决方案4】:

你可以使用:

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

HTH。但我认为大多数时候将其用于控制​​流或类似的东西并不是一个好习惯......

【讨论】:

  • 我用它来创建通用记录器,所以我将对象发送到记录器,它根据对象的类名进行记录,而不是每次都给出日志标记或日志字符串。谢谢
【解决方案5】:

对建议的任何方法的任何使用都被视为基于不良 OO 设计的代码异味。

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

任何建议的方法都可以,但在设计方面需要牢记。

【讨论】:

  • 是的,可能 99% 的 getClass 和 instanceof 使用都可以通过多态方法调用来避免。
  • 我同意。在这种情况下,我正在处理从 xml 生成的对象,这些对象遵循我没有所有权的设计不佳的架构。
  • 没有必要。有时接口的分离是好的。有时您想知道 A 是否是 B,但您不想强制要求 A 是 B,因为大多数功能只需要 A - B 具有可选功能。
  • 另外,有时您需要确保对象与您比较的对象属于同一类;例如,当我创建自己的类时,我喜欢重写 Object 的 equals 方法。我总是验证进来的对象是同一类的。
  • 另外,我想说的是告诉人们某些事情是不好的,而没有准确解释原因或提供对解释问题的论文、书籍或任何其他资源的参考被认为是不具建设性的。因此,知道我在 StackOverflow 中,我不知道为什么人们如此赞成这个答案。这里发生了一些变化……
【解决方案6】:

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

objectName.getClass().getName();

例子:-

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

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

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

【讨论】:

  • 这是正确的。仅使用obj.getClass() 将返回className,前缀为class
  • request.getClass().getName(); 打印所有包裹!以及类名
【解决方案7】:

Class”类还有一个.isInstance 方法。如果您通过myBanana.getClass() 获得对象的类,您可以通过

查看您的对象myApple 是否与myBanana 是同一类的实例
myBanana.getClass().isInstance(myApple)

【讨论】:

    【解决方案8】:

    如果你想在运行时知道的话,用isinstance() 检查是不够的。 使用:

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

    【讨论】:

      【解决方案9】:

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

       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 []
      

      【讨论】:

        【解决方案10】:

        我在我的 GeneralUtils 类中使用了打击功能,检查它可能有用

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

        【讨论】:

          【解决方案11】:

          您可以使用 getSimpleName()

          假设我们有一个对象:Dog d = new Dog(),

          我们可以使用下面的语句来获取类名:Dog。例如:

          d.getClass().getSimpleName(); // 返回字符串 'Dog'。

          PS:d.getClass() 会给你你的对象的全名。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2017-05-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-08
            • 2016-09-06
            • 2011-01-14
            相关资源
            最近更新 更多