请避免仅在Kotlin中提供答案,且答案要高于Android 21。
我正在尝试构建一个API解析器,该解析器使用类层次结构逻辑来表示API层次结构本身。通过这种结构,我能够以一种不复杂的方式解析该API,并且已经能够实现,但是我想进一步改进它。
我将开始解释我已经实现的内容。
这是我的应用将通过GET
接收,内部解析和分发的示例URL:
http://www.example.com/news/article/1105
在应用程序中,基本域无关紧要,但随后是API结构。
在这种情况下,我们混合使用了命令和变量:
要建立什么是命令和什么是变量,我构建了以下类结构:
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;
}
但是对于第二次尝试使用字段的逻辑,我无法正确调用final方法,这可能是因为最终的逻辑实际上是在尝试执行以下操作:
AbstractArticle.GET(42334);
代替
API.News.Article.GET(42334);
我怀疑是因为invoke
方法的第一个参数不再像以前一样是null
,而必须正确地与API.News.Article.GET(42334);
有没有办法使这项工作有效,或者有更好/不同的方式做到这一点?
答案 0 :(得分:0)
我发现我在使用实例字段的正确路径上,但是缺少必要的信息的一部分,以便最后正确地调用该方法。
当迭代字段时,我只使用每个字段的类,在使用静态类引用之前,这是完美的,因为它们不是实例,但是现在它需要该字段的实例才能正常工作。
最后,代替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
传递给我要调用的最终字段。