Java:使用反射还是将实例对象存储在列表中?

时间:2019-07-10 19:15:49

标签: java android performance reflection

你好吗?我正在尝试执行一些动态方法调用以在Java(Android)中的各种对象上获取sql字符串,但是我仍然遇到一些有关性能和稳定性的问题。

上下文示例::存储库类onCreate方法获取所有实体对象(表)并调用方法(例如getCreateTable)以获取要执行的sql字符串。

当然,我可以通过对每个方法进行类校准来显式调用类,但是我还有其他调用,例如“ dropTables”,“ truncateTables”等,而且我不想一直重复相同的结构。

public void CreateTables() {
    execute(Entity1.getCreateTable());
    execute(Entity2.getCreateTable());
    execute(Entity3.getCreateTable());
    [..]
    execute(Entity50.getCreateTable());
}

public void DropTables() {
    execute(Entity1.getDropTable());
    execute(Entity2.getDropTable());
    execute(Entity3.getDropTable());
    [..]
    execute(Entity50.getDropTable());
}

直到现在我知道我可以通过3种不同的方式做到这一点。

1)使用反射(当前正在使用):基本上,我将所有对象类存储在列表中,然后使用反射调用所需的静态方法。但是我知道反射不是永远应该是第一选择。

private final List<Class> entityList = new ArrayList<Class>() {
    {
        add(Entity1.class);
        add(Entity2.class);
        add(Entity3.class);
    }
};

public void createTables() {
    /* get all query strings */
    List<String> queryList = getQueryList("createTable");

    try {
        for (String query : queryList) {
            execute(query);
        }
    } catch (SQLException e) {
        [...]
    }
}

private List<String> getQueryList(String methodName) {
    List<String> queryList = new ArrayList<>();

    for (Class<?> objectClass : entityList) {
        try {
            Method[] ms = objectClass.getMethods();
            for (Method me : ms) {
                if (me.getName().equals(methodName)) {
                    String query = (String) me.invoke(null);

                    if (query != null && query.length() > 0) {
                        queryList.add((String) me.invoke(null));
                    }

                    break;
                }
            }
        } catch (Exception e) {
            [...]
        }
    }

    return queryList;
}

2)将对象实例存储在列表中:我可以创建一个包含实例对象的列表,然后将其强制转换为抽象父类(或接口),并调用方法以获取sql字符串。在这种情况下,我不知道在内存中保留实例对象列表是否是一个好习惯,也许这比根据列表大小使用反射更糟糕。

private final List<BaseEntity> entityList = new ArrayList<BaseEntity>() {
    {
        add(new Entity1(context));
        add(new Entity2(context));
        add(new Entity3(context));
    }
};

public void createTables() {
    for (BaseEntity entity : entityList) {
        try {
            execute(entity.getCreateTable());
        } catch (Exception e) {
            [...]
        }
    }
}

3)将所有字符串存储到JSON对象中:我尚未测试过该字符串,但是我敢肯定它可以使用。我可以调用“ init”方法来遍历所有对象,并使用所有sql字符串(删除,创建,截断等)创建JSON对象/数组。

非常感谢您与我分享您对这些方法(利弊)或其他更好解决方案的看法。

1 个答案:

答案 0 :(得分:0)

正如评论中指出的那样,这显然是一个糟糕的设计(这是我正在重构的一个旧项目)。因此,我决定摆脱反思,花一些时间重新设计代码本身。

我创建了一个基础超类来处理所有类似方法,并让实体/模型仅实现所需的单个规则,因此,数据库访问仅作为Singleton存储在一个类中。最好使用接口多态性。

通过这种方式,db类处理了动态SQL生成,以避免在各处重复相同的代码,并重复使用/回收实例列表以提高性能。

糟糕。 1:反射会降低性能,通常会使调试更加困难。当然,它可以节省一些时间,因为它实现起来很快,但是会禁用大多数IDE功能,因此在大多数情况下毫无用处。

糟糕。 2:也不应该使数据库实例列表保持活动状态。让多个实例同时访问数据库绝不是一个好主意,它可能导致DB锁定并重现意外的问题。

糟糕。 3:那个JSON东西……算了吧。我很抱歉建议这么丑。