Как я могу проверить, принадлежит ли класс Java JDK - PullRequest
3 голосов
/ 02 января 2012

Я использую внешнюю библиотеку, которая возвращает List<?>. Мне нужно проверить, является ли каждый объект этого списка объектом JDK (String, int, Integer ...). Это правильное решение?

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

Есть ли лучший?

Ответы [ 6 ]

5 голосов
/ 02 января 2012

В зависимости от вашего определения «объекта JDK» - которое может стать довольно размытым по краям - нет, это не собирается делать это.Пакет java.lang - это лишь малая часть всех классов, включенных в JDK.

Вы можете проверить, был ли каждый объект загружен тем же ClassLoader, который загружал java.lang.String, то есть * 1006.*

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

Как правило, для системных классов и классов приложений будет использоваться другая ClassLoader.

1 голос
/ 23 января 2012

Вы можете использовать ClassLoader.getSystemResources, а затем проверить, из какого jar загружен класс (например, если он исходит от rt.jar).

Вы получите такие URL, как:

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);
  }
    ....
  }
1 голос
/ 23 января 2012

Мы используем приведенный ниже класс, чтобы проверить, принадлежат ли классы 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() {
    }

}
1 голос
/ 02 января 2012

Это, вероятно, нормально, просто вы должны проверить следующие пакеты:

java
javax
com.sun
sun

, вероятно, другие ...

0 голосов
/ 13 сентября 2014

Я думаю, что проще решить эту проблему следующим образом: написать метод для идентификации всех классов, которые вы определили.В большинстве случаев все пользовательские классы следуют шаблону, подобному com.something.something.Тогда, если они не принадлежат com.something.something, это класс JDK

0 голосов
/ 09 января 2012

Лично мне нравится базовый ответ загрузчика классов.Но он вернет истину и на StringBuilder.Если вы хотите более узкое определение, которое является только «встроенными» типами, вы можете попытаться оценить, является ли это примитивным типом (таким как 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.BigDecimal, java.util.Date, java.sql.Timestamp.Обратите внимание, однако, что они не являются окончательными, поэтому я предположил, что если кто-то расширит их даже тривиальным способом, он не будет рассматриваться как класс JDK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...