在一个工程中有多个城市,每个城市对应一个类,每个类有一个TheCity注解来标识这个类是那个城市,我们需要在这些类中找到我们想要找的城市。
TheCity注解类:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TheCity {
//城市
public String cityName() default "";
}
贵州的城市类的定义:
@TheCity(cityName="贵州")
public class GuiZhou extends CityBase {
@Override
public void getStr() {
System.out.println("我是贵州"+"************"+this.str);
}
}
上海的城市类定义:
@TheCity(cityName="上海")
public class ShangHai extends CityBase {
@Override
public void getStr() {
System.out.println("我是上海"+"************"+this.str);
}
}
这里还有其他城市和上面类似,只是TheCity中的cityName值不同,这些类可以在一个包或者不同包下面。
显然,我们需要根据用户来确定我们需要加载哪个类,
想法:我们可以把整个工程下的类都先加载到一个map集合中,之后对比TheCity注解的cityName的值是否是用户输入的,是的话我们就实例化这个类。
ClassLoaderUntil类:加载整个工程中的类
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
public class ClassLoaderUntil {
/**
* 返回指定包或者整个工程中的类
* @param clazz
* @param packageStr
* @return
* @throws IOException
*/
public static List<Class> getTheCityClass(Class clazz,String packageStr) throws IOException{
List<Class> classList = null;
classList = new ArrayList<Class>();
ClassLoader classLoader = clazz.getClassLoader();
Enumeration<URL> resources = null;
if(packageStr!=null&&!packageStr.equals("")){
String path = packageStr.replace(".", "/");
resources = classLoader.getResources(path);
}else{
resources = classLoader.getResources("");
}
List<File> fileList = new ArrayList<File>();
while(resources.hasMoreElements()){
URL nextElement = resources.nextElement();
fileList.add(new File(nextElement.getFile()));
}
for (File file : fileList) {
try {
classList.addAll(getClassList(file));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return classList;
}
/**
* 根据包名加载类
* @param clazz
* @param packageStr
* @return
* @throws IOException
*/
private static List<Class> getClassList(File dir) throws ClassNotFoundException {
List<Class> Clist = new ArrayList<Class>();
String packageName = getPackageName(dir.getPath());
if(dir.isDirectory()){
File[] files = dir.listFiles();
for (File file : files) {
String string = null;
if(file.getName().contains(".")){//如果是以.class文件结尾就加载,否则需要继续向下找.class文件
if(packageName.equals("")){
string = file.getName().substring(0, file.getName().length()-6);
}else{
string = packageName+"."+file.getName().substring(0, file.getName().length()-6);
}
try {
Clist.add(Class.forName(string));
} catch (Exception e) {
System.out.println(string+"类不能被加载");
}
}else{
Clist.addAll(getClassList(file));
}
}
}else if(dir.getName().endsWith(".class")){
String string = packageName+"."+dir.getName().substring(0, dir.getName().length()-6);
Clist.add(Class.forName(string));
}
return Clist;
}
/**
* 取得包名
* @param packageName
* @return
*/
public static String getPackageName(String packageName){
int indexOf = packageName.indexOf("classes");
String substring = null;
try {
substring = packageName.substring(indexOf + 8, packageName.length());//classes后面有\
} catch (Exception e) {
substring = packageName.substring(indexOf + 7, packageName.length());//第一次classes后面没有\
}
return substring.replace("\\", ".");
}
}
测试类:
public static void main(String[] args) throws IOException {
List<Class> theCityClass = ClassLoaderUntil.getTheCityClass(MyCity.class,null);
System.out.println("整个工程中有"+theCityClass.size()+"个类");
//开始需找带有注解的城市类
HashMap<String, Class> cityClassMap = new HashMap<String, Class>();
//循环我们找到的类,
for (Class cl : theCityClass) {
//得到是否有TheCity注解,
TheCity annotation = (TheCity) cl.getAnnotation(TheCity.class);
if(annotation!=null){
cityClassMap.put(annotation.cityName(), cl);
CityBase myCl = null;//城市类都继承与CityBase类
try {
System.out.println(annotation.cityName());
//这里可以和用户想要的的城市做比较,比如是贵州annotation.cityName().equals("贵州") 之后就对这个类进行操作
myCl = (CityBase) cl.newInstance();
} catch (Exception e) {}
}
}
System.out.println("有TheCity注解的类有"+cityClassMap.size()+"个");
工程中有TheCity注解的类的位置
结果: