如何检查类是否属于Java JDK

时间:2012-01-02 17:41:25

标签: reflection java

我使用外部库返回一些List<?>。 我需要检查此列表的每个对象是否是JDK的对象(String,int,Integer ...)。 这是一个合适的解决方案吗?

List<?> list = externalLibrary.search(...);
for(clazz : list) {
    if (clazz.getPackage().getName().startsWith("java.lang"))
      // do something different
}

有更好的吗?

6 个答案:

答案 0 :(得分:5)

根据你对“JDK对象”的定义 - 它可能会在边缘变得非常模糊 - 不,这不会做到这一点。 java.lang包只是JDK中包含的所有类的一小部分。

您可以检查每个对象是否由加载ClassLoader的同一java.lang.String加载 - 即,

if (theObject.getClass().getClassLoader() == "".getClass().getClassLoader()) ...

通常,系统类与应用程序类将使用不同的ClassLoader

答案 1 :(得分:1)

可能没问题,只需要检查以下包裹:

java
javax
com.sun
sun

可能是其他人......

答案 2 :(得分:1)

我们使用下面的类来检查类是否属于JDK

public class JDKClass {

    private static Set<String> CS = new HashSet<String>();

    static {
        try {
            File file = new File(System.getProperty("java.home"),
                    "lib/classlist");
            BufferedReader r = new BufferedReader(new FileReader(file));
            String l;
            while (true) {
                l = r.readLine();
                if (l == null) {
                    break;
                } else {
                    CS.add(l.replace('/', '.'));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static boolean contains(String o) {
        return CS.contains(o) || o.startsWith("java") || o.startsWith("com.sun")
                || o.startsWith("sun") || o.startsWith("oracle")
                || o.startsWith("org.xml") || o.startsWith("com.oracle");
    }

    private JDKClass() {
    }

}

答案 3 :(得分:1)

您可以使用ClassLoader.getSystemResources,然后检查加载的类是什么样的jar(例如,如果它来自rt.jar)。

您将获得以下网址:

jar:file:/C:/Users/user/.m2/repository/org/slf4j/slf4j-log4j12/1.6.1/slf4j-log4j12-1.6.1.jar!/org/slf4j/impl/StaticLoggerBinder.class

取自SLF4j的示例代码:

  private static String STATIC_LOGGER_BINDER_PATH = 
     "org/slf4j/impl/StaticLoggerBinder.class";
  private static void singleImplementationSanityCheck() {
    try {
      ClassLoader loggerFactoryClassLoader = LoggerFactory.class
          .getClassLoader();
      Enumeration paths;
      if (loggerFactoryClassLoader == null) {
        paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
      } else {
        paths = loggerFactoryClassLoader
            .getResources(STATIC_LOGGER_BINDER_PATH);
      }
  List implementationList = new ArrayList();
  while (paths.hasMoreElements()) {
    URL path = (URL) paths.nextElement();
    implementationList.add(path);
  }
    ....
  }

答案 4 :(得分:0)

我个人喜欢类加载器基础答案。但它也会在StringBuilder上返回true。如果你想要更简洁的定义,只有&#34;内置&#34;类型,您可以尝试评估这是原始类型(如int)还是包装类型(如Integer)或String。你可以这样写:

    import java.util.Map;
    import java.util.TreeMap;



    public class Utils {

        private static Map<String, Class<?>> SUBST_MAP = new TreeMap<String, Class<?>>();
        private static Map<String, Class<?>> SIMPLE_MAP = new TreeMap<String, Class<?>>();


        static {
            SUBST_MAP.put(Byte.class.getName(), Byte.TYPE);
            SUBST_MAP.put(Short.class.getName(), Short.TYPE);
            SUBST_MAP.put(Integer.class.getName(), Integer.TYPE);
            SUBST_MAP.put(Long.class.getName(), Long.TYPE);
            SUBST_MAP.put(Float.class.getName(), Float.TYPE);
            SUBST_MAP.put(Double.class.getName(), Double.TYPE);
            SUBST_MAP.put(Boolean.class.getName(), Boolean.TYPE);
            SUBST_MAP.put(Character.class.getName(), Character.TYPE);
            SIMPLE_MAP.put(String.class.getName(), Boolean.TRUE);

        }




    /**
     * Gets the the class type of the types of the argument.
     * 
     * if substPrimitiveWrapper is true,
     * then if there is argument, that represent primitive type wrapper (such as Integer),
     *      then it will be substituted to primitive type (such as int).
     * else no substitution will be done.
     *
     * @param arg object.
     * @param substPrimitiveWrapper - wheteher to do primitive type substitution.
     * @retrun class type.
     */

    public static Class<?> getClassType(Object arg, boolean substPrimitiveWrapper){
        Class<?> classType = null;
        String className = null;
        Class<?> substClass = null;

        if(arg != null ){
            //making default classType
            classType = arg.getClass();
            if(substPrimitiveWrapper){
                className = classType.getName();
                substClass = (Class<?>)SUBST_MAP.get(className);
                if(substClass != null){
                    classType = substClass;
                }

            }
        }
        return classType;
    }

    /**
     * This method consider JDK type any primitive type, wrapper class or String.
     * 
     * 
     * @param arg object
     * @return where arg is JDK type or now.
     */
    public static boolean isJDKClass(Object arg){
        Class<?> classType = getClassType(arg, true);
        boolean isJDKClass = false;
        if(classType!=null){
            //if(String.class.equals(classType)){
            //  isJDKClass = true; //this is String, note that String is final
            //}
            assert classType!=null;
            String className = classType.getName();
            Boolean isFound = (Boolean)SIMPLE_MAP.get(className);
            if(Boolean.TRUE.equals(isFound)){
                isJDKClass = true; //this is predefined class
            }


            boolean isPrimitiveType = classType.isPrimitive();
            if(isPrimitiveType){
                isJDKClass = true; //this is primitive type or wrapper class
            }
        }

        return isJDKClass;
     }

    } 

您还可以选择添加对java.math.BigDecimaljava.util.Datejava.sql.Timestamp等类的支持。但是请注意,它们不是最终的,所以我假设如果有人甚至以普通方式扩展它们,它将不会被视为JDK类。

答案 5 :(得分:0)

我认为更简单的解决方案是以这种方式解决问题: 编写一个方法来识别您定义的所有类。在大多数情况下,所有用户定义的类都遵循com.something.something之类的模式。然后,如果它们不属于com.something.something,则它是JDK类