首页 文章

用反射连续迭代场的场

提问于
浏览
0

请避免仅在Kotlin中提供答案且高于Android 21 .

我正在尝试构建一个API解析器,它使用类层次结构逻辑来表示API层次结构本身 . 有了这个结构,我能够以简单的方式解析API,我已经能够实现这一点,但我想进一步改进它 .

我将开始解释我已经实施的内容 .

这是我的应用程序将通过 GET ,内部解析和分派接收的示例网址:

http://www.example.com/news/article/1105

在应用程序中,基本域是无关紧要的,但接下来是API结构 .

在这种情况下,我们有命令和变量的混合:

  • 新闻(命令)

  • 文章(命令)

  • 1105(变量)

为了 Build 什么是命令以及什么是变量,我构建了以下类结构:

public class API {
    public static final News extends AbstractNews {}
}

public class AbstractNews {
    public static final Article extends AbstractArticle {}
}

public class Article {
    public static void GET(String articleId) {
        // ...
    }
}

我在分割URL之后迭代遍历每个类,同时从API类开始将每个命令与每个类(或子类)相匹配 . 在我到达分割URL的末尾之前,任何失败的匹配都将作为变量存储在单独的列表中 .

对于上面提供的示例,该过程如下:

拆分URL每个正斜杠(忽略基域)

/news/article/1105

List<String> stringList = [
    news, 
    article,
    1105
];

迭代拆分列表中的每个项目并再次匹配API结构化类(以下仅是示例示例,它不是我目前实现的100%):

List<String> variableList = new ArrayList<>();
Class lastClass = API.class;

for (String stringItem : stringList) {

    if ((lastClass = classHasSubClass(lastClass, stringItem)) != null) {
        continue;
    }

    variableList.add(stringItem);

}

一旦到达列表的末尾,我检查最后一个类是否包含请求方法(在本例中为 GET ),并与变量列表一起调用 .

就像我之前所说的那样,它工作得非常好,但是它会使每个类直接暴露出来,因此他们可以被项目中的任何其他人直接和错误地访问,所以我试图让层次结构更加包含 .

我想保持通过层次结构访问方法的能力,因此仍然可以实现以下功能:

API.News.Article.GET(42334);

虽然与此同时我也不希望它也可以做到以下几点:

AbstractArticle.GET(42334);

我已经尝试将每个子类转换为类实例字段

public class API {
    // this one is static on purpose to avoid having to instantiate
    // the API class before accessing its fields
    public static final AbstractNews News = new AbstractNews();
}

public class AbstractNews {
    public final AbstractArticle Article = new AbstractArticle();
}

public class Article {
    public void GET(String articleId) {
        // ...
    }
}

这适用于我之前想要实现的两点,但是我无法找到一种方法来迭代类字段,这种方式允许我正确地调用最终方法 .

对于之前的逻辑,我需要迭代的是以下内容:

private static Class classHasSubClass(Class<?> currentClass, String fieldName) {

    Class[] classes;

    classes = currentClass.getClasses();

    for (final Class classItem : classes) {
        if (classItem.getSimpleName().toLowerCase().equals(fieldName)) {
            return classItem;
        }
    }

    return null;

}

但是对于使用字段的第二次逻辑尝试,我无法正确调用最终方法,可能是因为生成的逻辑实际上是在尝试执行以下操作:

AbstractArticle.GET(42334);

代替

API.News.Article.GET(42334);

我怀疑是因为 invoke 方法的第一个参数不再像以前那样 null 而且必须是 API.News.Article.GET(42334); 的正确等价物

有没有办法使这项工作或有更好/不同的方式这样做?

1 回答

  • 0

    我发现我在实例字段的正确路径上,但是在最后正确地调用方法时缺少必要信息的一部分 .

    在迭代字段时,我只使用了每个字段的Class,这在使用静态类引用之前工作得很好,因为那些不是实例,但是现在它需要字段的实例才能正常工作 .

    最后,用于代替 classHasSubClass 的迭代方法使其工作如下:

    private static Object getFieldClass(Class<?> currentClass, Object currentObject, final String fieldName) {
    
        Field[] fieldList;
    
        fieldList = currentClass.getDeclaredFields();
    
        for (final Field field : fieldList) {
            if (field.getName().toLowerCase().equals(fieldName)) {
    
                try {
                    return field.get(currentObject);
                } catch (IllegalAccessException e) {
    
                    e.printStackTrace();
                    break;
    
                }
    
            }
        }
    
        return null;
    
    }
    

    有了这个,我总是将一个实例对象引用到我要调用的最后一个字段作为第一个参数( someMethod.invoke(objectInstance); )而不是 null .

相关问题