安卓开发者都知道,安卓有个R类用于管理资源,可以防止书写路径出错。我想Java也可以借鉴这个思路,对资源目录自动生成R类。
而且安卓因为JDK限制没法反复嵌套内部类,但是Java没有这个限制。
开干,实际就是递归文件夹生成代码
public class MakeR {
private static final String CLASS_NAME="R";
private static final String BASE_PATH="src/main/java";
@SneakyThrows
public static void make(String src, String tar) {
String classStr=buildClass(src,tar);
Path path=getPath(tar);
Files.write(path,classStr.getBytes());
}
private static Path getPath(String tar) {
String[] split = tar.split("\\.");
String[] copy = Arrays.copyOf(split, split.length + 1);
copy[split.length]=CLASS_NAME+".java";
return Paths.get(BASE_PATH,copy);
}
private static String buildClass(String src, String tar) {
StringBuilder builder=new StringBuilder();
buildPackage(builder,tar);
buildCreate(builder);
buildStart(builder);
buildBody(builder,src);
buildEnd(builder);
return builder.toString();
}
private static void buildEnd(StringBuilder builder) {
builder.append("}");
}
private static void buildBody(StringBuilder builder, String src) {
File file = new File(src);
if(file.isFile())throw new RuntimeException("构建对象必须是文件夹!!!");
buildFolder(builder,file,1);
}
private static void buildFolder(StringBuilder builder, File folder, int tabNum) {
File[] files = folder.listFiles();
for (File file:files){
if(file.isDirectory()){
buildTabs(builder,tabNum);
builder.append("interface ").append(file.getName()).append("{\n\n");
buildFolder(builder,file,tabNum+1);
buildTabs(builder,tabNum);
builder.append("}\n\n");
}else {
buildTabs(builder,tabNum);
builder.append("String ").append(trimFileName(file.getName())).append("=\"")
.append(file.getAbsolutePath().replaceAll("\\\\","/"))
.append("\";\n");
}
}
}
private static String trimFileName(String name) {
int index = name.lastIndexOf('.');
if(index==-1)return name;
return name.substring(0,index);
}
private static void buildTabs(StringBuilder builder, int tabNum) {
for (int i = 0; i < tabNum; i++) {
builder.append("\t");
}
}
private static void buildStart(StringBuilder builder) {
builder.append("public interface R {\n\n");
}
private static void buildCreate(StringBuilder builder) {
builder.append("/**\n * @author MakeR\n */\n");
}
private static void buildPackage(StringBuilder builder, String tar) {
builder.append("package part5;\n\n");
}
public static void make(String src) {
String tar=getPackage();
make(src,tar);
}
//根据调用堆栈 获取调用包名
private static String getPackage() {
StackTraceElement element = Thread.currentThread().getStackTrace()[3];
String className = element.getClassName();
return className.substring(0,className.lastIndexOf('.'));
}
}
调用生成结果
使用过程
我从去年开始陆续写了不少代码生成器,感觉真是就像搬砖一样,下一步,看看能不能根据书写的class模板文件自动生成对应代码。