我使用外部库返回一些List<?>
。
我需要检查此列表的每个对象是否是JDK的对象(String,int,Integer ...)。
这是一个合适的解决方案吗?
List<?> list = externalLibrary.search(...);
for(clazz : list) {
if (clazz.getPackage().getName().startsWith("java.lang"))
// do something different
}
有更好的吗?
答案 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.BigDecimal
,java.util.Date
,java.sql.Timestamp
等类的支持。但是请注意,它们不是最终的,所以我假设如果有人甚至以普通方式扩展它们,它将不会被视为JDK类。
答案 5 :(得分:0)
我认为更简单的解决方案是以这种方式解决问题: 编写一个方法来识别您定义的所有类。在大多数情况下,所有用户定义的类都遵循com.something.something之类的模式。然后,如果它们不属于com.something.something,则它是JDK类