【问题标题】:Is there any way to check whether a given class type belongs to Java object or custom object有什么方法可以检查给定的类类型是属于 Java 对象还是自定义对象
【发布时间】:2013-09-28 20:43:14
【问题描述】:

我正在寻找任何方法来检查类的给定属性的类型是自定义对象类型(例如,Person)还是 Java 对象(例如,String、Long、原始类型)类型。如果使用 instanceof,检查所有 Java 类型会很忙。任何人都可以建议一种方法来检查,如果存在这样的东西。

【问题讨论】:

  • Java 有许多内置类和接口,例如 List。你的代码应该如何反应让我们说ArrayList 实例?
  • 这就是我想知道的。简单来说,如果我的自定义类有 5 个类型的属性 - String、int、Long、List、自定义对象。如果是这种情况,使用反射我可以获得各个字段的类型。但是拿到类型后,有什么办法可以识别是java内置类型还是自定义类型呢?
  • @Sarath 但是您认为“内置 java 类型”是什么? 正如这里的几个人所讨论的,这个问题有很多可能的答案,具体取决于 b>你需要它。
  • 所以,从人们对这个问题的回答中我可以理解的一件事是,没有直接的方法来检查该类是否属于内置 java 类型或自定义对象,而是检查对于类包声明的正则表达式是唯一的方法。如果我错了,请纠正我。
  • @Sarath 你想解决什么问题?如果这是关于持久化值对象,您应该看看JPA,特别是它使用注释来定义有意义的持久性字段的方式

标签: java class reflection types


【解决方案1】:

尝试使用对象来自的包的实现 vendor 标题。似乎标准 Java 包将此值设置为 "Oracle Corporation" "Java Runtime Environment".

public static boolean isJavaLang(Object check) {
    if (check == null)// lets say that null comes from JRE
        return true;

    return isJavaLang(check.getClass());
}

public static boolean isJavaLang(Class<?> check) {

    Package p = check.getClass().getPackage();

    if (p == null) // default package is package for users classes
        return false;

    String title = p.getImplementationTitle();
    if (title == null)// no title -> class not from Oracle
        return false;

    // System.out.println(p.getImplementationVendor());
    // System.out.println(p.getImplementationTitle());
    return title.equals("Java Runtime Environment");
}

【讨论】:

  • 感谢您的回答。我看到“Sun Microsystems, Inc.”用于 Java 类的 implementationVendor。这真的很有帮助。
  • @Sarath 你能说明你从哪个包/对象中得到这个供应商吗?似乎它来自一些遗留类,Oracle 并没有将它从 Sun 更改为 Oracle。无论如何,试试p.getImplementationVendor() 并将其与"Java Runtime Environment" 进行比较。
  • 再次感谢。 implementationTitle 返回“Java 运行时环境”, implementationVendor 返回“Sun Microsystems, Inc.”对于我尝试过的一些随机 Java 内置类,对于自定义对象和第三方对象为 null。我尝试过的 java 类 - SwingUtilities.class、ArrayList.class、List.class。我正在使用 JRE 1.6。
  • 作为参考,这个数据并不神奇。这些值实际上来自META-INF/MANIFEST.MF。如果未设置条目 Implementation-Title,则此 API 将返回 nullrt.jar 清单声明:Implementation-Title: Java Runtime Environment 以及供应商、版本等其他信息。
【解决方案2】:

没有故障安全方法可以做到这一点。正如其他人所说,Java 建立在常规类的基础之上。

我想,除了原语,这一切都归结为您自己对“JDK 的类”、“我的类”和“第 3 方类”的定义。

@splunebob 的解决方案适用于您自己的单个树分支类。

我认为以下包中的类可以安全地被视为 JDK 的:

java.lang.*
java.*
javax.*
com.sun.*
com.oracle.*

您还可以添加一些常见的 3rd 方,例如 org.apache.*

【讨论】:

    【解决方案3】:

    Java 非常“建立在自身之上”。大部分 SDK 可以被视为“自定义”或“内置”,具体取决于您查看的方式。

    例如,Exception 是 Java 内置的,但也是用 Java 编写的。您可以自己编写类似的代码,但是根据您所说的,我猜您会认为它是“Java 对象”。

    同样,ArrayList 也是用 Java 编写的,但因为它是一个实用程序类,我猜你会认为它是“自定义”的,虽然我不确定,因为它仍然包含在 SDK 中。

    在不确切知道您在寻找什么的情况下,我可以根据您所说的(StringLong 等)猜测出最接近的分组是 java.lang 包。在words of the SDK documentation 本身中,java.lang 包:

    提供 Java 编程语言设计的基础类。

    您可以检查该对象的类的包名是否在java.lang中:

    static class A {
        
    }
    
    public static void main (String[] args) {
        String test1 = "";
        A test2 = new A();
        int test3 = 3;
    
        System.out.println(isJavaLang(test1));
        System.out.println(isJavaLang(test2));
        System.out.println(isJavaLang(test3));
    }
    
    public static boolean isJavaLang(Object check) {
        return check.getClass().getName().startsWith("java.lang");
    }
    

    Working example

    【讨论】:

    • 如果是这种情况,例如对于来自 javax.* 和其他包的原始类型和类,这将不起作用。只是一个随机的例子。 javax.swing.ActionMap c = new javax.swing.ActionMap(); System.out.println(c.getClass().getName());将返回 javax.swing.ActionMap
    • @Sarath 但那些不是“原始的”。我已经更新了我的答案来解释。之前我认为您正在寻找“基本”Java 对象,但现在听起来您正在寻找 SDK 定义的任何东西?请在您驳回这是否对您有帮助之前澄清该要求。
    • @Sarath 另外,实际上它适用于原语。当传递给需要Object的函数调用时,原语是autoboxed,并且包装类都在java.lang中。
    • Pshemo 发布了一个答案。这是我试过的,它的工作原理。你能更新一下吗?它不使用包名称,而是使用 implementationVendor 和 implementationTitle。与您的答案相似但不同。你给的也有效。但问题是,它更像是列出所有可能的包。如果我错了,请纠正我。
    • @Sarath 当然,这听起来像是一个很好的解决方案,除了“实现供应商”或“实现标题”可能会因 JRE 而异,而包名称很可能总是“java”。如果您希望它为 SDK 中的任何内容返回“true”,您可以将其与“java”而不是“java.lang”进行比较。
    【解决方案4】:

    假设您自己的类不在名称以java* 开头的包中:

    public static <T> boolean isJDKClass(T t) {
         return t.getClass().getPackage().getName().startsWith("java");
    }
    

    【讨论】:

      【解决方案5】:

      我想你想要这样的东西:

      public static boolean isJavaObject(Object obj)
      {
        return (! obj.getClass().getName().startsWith("my.package"));
      }
      

      "my.package" 是包层次结构的负责人。

      【讨论】:

        【解决方案6】:

        我不完全确定你的问题是对的......

        java.lang.Class 类包含一些您可以使用的工具。

        isPrimitive() 函数

        确定指定的 Class 对象是否表示原始类型。 有九个预定义的 Class 对象来表示八种原始类型和 void。它们由 Java 虚拟机创建,与它们所代表的基本类型具有相同的名称,即 boolean、byte、char、short、int、long、float 和 double。

        这些对象只能通过以下公共静态最终变量访问,并且是该方法返回 true 的唯一 Class 对象。

        至于其他类,没有“Java 对象”之类的东西——每个对象都是一个 Java 对象……但是您可以检查相关类的名称是否以 java.lang. 前缀开头,但java.lang package 也包含很多不同的东西,不仅是您想要查找的基本数据类型。

        【讨论】:

          猜你喜欢
          • 2022-01-25
          • 2012-11-26
          • 2013-07-12
          • 1970-01-01
          • 1970-01-01
          • 2014-07-28
          • 1970-01-01
          • 1970-01-01
          • 2021-09-11
          相关资源
          最近更新 更多