public class ClassUtil {
public static String getCallerClassName(int callStackDepth) {
return Thread.currentThread().getStackTrace()[callStackDepth].getClassName();
}
public static boolean hasDeclaredMethod(Class> clazz, String methodName, Class>... checkedParameters) {
Method[] methods = clazz.getDeclaredMethods();
for (Method m : methods) {
if (m.getName().equals(methodName)) {
Class>[] params = m.getParameterTypes();
if (params.length == checkedParameters.length) {
boolean isEqual = true;
for (int i = 0; i < params.length; i++) {
if (!params[i].equals(checkedParameters[i])) {
isEqual = false;
}
}
if(isEqual == true){
return isEqual;
}
}
}
}
return false;
}
public static List> getSubClasses(Class clazz, Package pack) {
Set> allClassesInPackage = getClasses(pack);
return getSubClasses(clazz, allClassesInPackage);
}
private static ArrayList> getSubClasses(Class clazz, Collection> allClassesInPackage) {
ArrayList> subClasses = new ArrayList>();
for (Class> tmpClass : allClassesInPackage) {
if (clazz.isAssignableFrom(tmpClass) && !tmpClass.isAssignableFrom(clazz)) {
subClasses.add(tmpClass.asSubclass(clazz));
}
}
return subClasses;
}
public static List> getSubClasses(Class clazz) {
return getSubClasses(clazz, loadClassesFromPath());
}
/**
* ä»å
packageä¸è·åææçClass
* @param pack
* @return
*/
public static Set> getClasses(Package pack) {
// 第ä¸ä¸ªclassç±»çéå
Set> classes = new LinkedHashSet>();
// æ¯å¦å¾ªç¯è¿ä»£
boolean recursive = true;
// è·åå
çåå å¹¶è¿è¡æ¿æ¢
String packageName = pack.getName();
String packageDirName = packageName.replace('.', '/');
// å®ä¹ä¸ä¸ªæä¸¾çéå å¹¶è¿è¡å¾ªç¯æ¥å¤çè¿ä¸ªç®å½ä¸çthings
Enumeration dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
// 循ç¯è¿ä»£ä¸å»
while (dirs.hasMoreElements()) {
// è·åä¸ä¸ä¸ªå
ç´
URL url = dirs.nextElement();
// å¾å°åè®®çåç§°
String protocol = url.getProtocol();
// 妿æ¯ä»¥æä»¶çå½¢å¼ä¿å卿å¡å¨ä¸
if ("file".equals(protocol)) {
// è·åå
çç©çè·¯å¾
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以æä»¶çæ¹å¼æ«ææ´ä¸ªå
ä¸çæä»¶ å¹¶æ·»å å°éåä¸
findAndAddClassesInPackageByFile(packageName, filePath, true, classes);
} else if ("jar".equals(protocol)) {
// 妿æ¯jarå
æä»¶
// å®ä¹ä¸ä¸ªJarFile
JarFile jar;
try {
// è·åjar
jar = ((JarURLConnection) url.openConnection()).getJarFile();
// 仿¤jarå
å¾å°ä¸ä¸ªæä¸¾ç±»
Enumeration entries = jar.entries();
String jarPackageName = packageName;
// åæ ·çè¿è¡å¾ªç¯è¿ä»£
while (entries.hasMoreElements()) {
// è·åjaréçä¸ä¸ªå®ä½ å¯ä»¥æ¯ç®å½ åä¸äºjarå
éçå
¶ä»æä»¶ å¦META-INFçæä»¶
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 妿æ¯ä»¥/å¼å¤´ç
if (name.charAt(0) == '/') {
// è·ååé¢çå符串
name = name.substring(1);
}
// 妿ååé¨ååå®ä¹çå
åç¸å
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 妿以"/"ç»å°¾ æ¯ä¸ä¸ªå
if (idx != -1) {
// è·åå
å æ"/"æ¿æ¢æ"."
jarPackageName = name.substring(0, idx).replace('/', '.');
}
// 妿å¯ä»¥è¿ä»£ä¸å» 并䏿¯ä¸ä¸ªå
if ((idx != -1) || recursive) {
// 妿æ¯ä¸ä¸ª.classæä»¶ èä¸ä¸æ¯ç®å½
if (name.endsWith(".class") && !entry.isDirectory()) {
// 廿åé¢ç".class" è·åçæ£çç±»å
String className = name.substring(jarPackageName.length() + 1, name.length() - 6);
try {
// æ·»å å°classes
classes.add(Class.forName(jarPackageName + '.' + className, false, Thread.currentThread()
.getContextClassLoader()));
} catch (ClassNotFoundException e) {
Logger.error("æ·»å ç¨æ·èªå®ä¹è§å¾ç±»é误 æ¾ä¸å°æ¤ç±»ç.classæä»¶");
}
}
}
}
}
} catch (IOException e) {
Logger.error("卿«æç¨æ·å®ä¹è§å¾æ¶ä»jarå
è·åæä»¶åºé");
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
/**
* 以æä»¶ç形弿¥è·åå
ä¸çææClass
* @param packageName
* @param packagePath
* @param recursive
* @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive, Set> classes) {
// è·åæ¤å
çç®å½ 建ç«ä¸ä¸ªFile
File dir = new File(packagePath);
// 妿ä¸å卿è
ä¹ä¸æ¯ç®å½å°±ç´æ¥è¿å
if (!dir.exists() || !dir.isDirectory()) {
Logger.error("ç¨æ·å®ä¹å
å " + packageName + " 䏿²¡æä»»ä½æä»¶");
return;
}
// 妿åå¨ å°±è·åå
ä¸çæææä»¶ å
æ¬ç®å½
// èªå®ä¹è¿æ»¤è§å 妿å¯ä»¥å¾ªç¯(å
å«åç®å½) æåæ¯ä»¥.classç»å°¾çæä»¶(ç¼è¯å¥½çjavaç±»æä»¶)
File[] dirfiles = dir.listFiles(file -> (recursive && file.isDirectory()) || (file.getName().endsWith(".class")));
// å¾ªç¯æææä»¶
for (File file : dirfiles) {
// 妿æ¯ç®å½ åç»§ç»æ«æ
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive, classes);
} else {
// 妿æ¯javaç±»æä»¶ 廿åé¢ç.class åªçä¸ç±»å
String className = file.getName().substring(0, file.getName().length() - 6);
try {
// æ·»å å°éåä¸å»
classes.add(Class.forName(packageName + '.' + className, false, Thread.currentThread().getContextClassLoader()));
} catch (ClassNotFoundException e) {
Logger.error("æ·»å ç¨æ·èªå®ä¹è§å¾ç±»é误 æ¾ä¸å°æ¤ç±»ç.classæä»¶:" + className);
}
}
}
}
public static ArrayList> loadClassesFromPath() {
ArrayList> result = new ArrayList>();
try {
URL resource = ClassUtil.class.getResource("/");
URI uri = resource.toURI();
String property = new File(uri).getPath();
String[] paths = property.split(";");
for (String path : paths) {
File file = new File(path);
if (file.isFile() && path.endsWith(".jar")) {
result.addAll(listClassesInZip(file));
} else if (file.isDirectory()) {
result.addAll(listClassesInDirectory(path + File.separatorChar, file));
}
}
} catch (URISyntaxException e) {
Logger.error("Error!", e);
}
return result;
}
private static ArrayList> listClassesInDirectory(String rootPath, File file) {
ArrayList> result = new ArrayList>();
File[] subFiles = file.listFiles();
for (File subFile : subFiles) {
if (subFile.canRead()) {
if (subFile.isFile()) {
String path = subFile.getPath();
if (path.endsWith(".class")) {
try {
String className = getClassName(path.substring(rootPath.length()));
result.add(Class.forName(className, false, Thread.currentThread().getContextClassLoader()));
} catch (Throwable e) {
Logger.error("error!", e);
}
} else if (path.endsWith(".jar")) {
result.addAll(listClassesInZip(subFile));
}
} else if (subFile.isDirectory()) {
result.addAll(listClassesInDirectory(rootPath, subFile));
}
}
}
return result;
}
private static ArrayList> listClassesInZip(File jarFile) {
ArrayList> result = new ArrayList>();
ZipInputStream in = null;
try {
in = new ZipInputStream(new FileInputStream(jarFile));
ZipEntry ze = null;
while ((ze = in.getNextEntry()) != null) {
if (ze.isDirectory()) {
continue;
} else {
try {
String name = ze.getName();
if (!name.endsWith(".class"))
continue;
String className = getClassName(name);
result.add(Class.forName(className, false, Thread.currentThread().getContextClassLoader()));
} catch (Throwable e) {
Logger.error("Error!", e);
}
}
}
} catch (Throwable e) {
Logger.error("Error!", e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
Logger.error("Error!", e);
}
}
}
return result;
}
private static String getClassName(String path) {
return path.replace('/', '.').replace('\\', '.').replaceAll(".class", "");
}
}