Java5之前的集合和不愿意更改

xeufq47z  于 2021-06-30  发布在  Java
关注(0)|答案(10)|浏览(255)

我们有几个区域可以看到这样的代码

public Map extractData(ResultSet rs) throws SQLException, DataAccessException {
        Map m = new HashMap();
            while(rs.next()){
                    Jurisdiction j = new Jurisdiction();
                    m.put("code",rs.getLong(1) );
                    m.put("type",rs.getString(2));
                    m.put("id",rs.getLong(3) )
            }
        return m;
        }

效果很好。问题是我很难找到一个理由来重新写一个“通用”的方式,如果我做了什么“真正的”好处 Map<String,Object> m 给我(除了跳跃 String 钥匙)?

sbtkgmzw

sbtkgmzw1#

如果代码可以工作,那么重写代码可能没有什么好处。但是,除了编译时类型检查之外,您可能希望切换到使用泛型的另一个原因是它使代码自文档化。它明确了它所使用的类型。

r7xajy2e

r7xajy2e2#

好处是,任何调用者都可以假设键是字符串,这不是因为他们熟悉代码,也不是因为他们非常确定自己知道Map是如何构造的,而是因为语言强制执行了Map。值的异构性也被明确指定。
这可能看起来很愚蠢,因为你知道代码已经可以工作了,但是我遇到过这样的情况:你必须将遗留代码或libs集成到一个通用的应用程序中,并且已知类型和未知Map之间的界限非常明显。对于Map的消费者,你要么
假设键是一个字符串(错误的做法)
挖掘源代码(如果可以的话),让自己相信键总是字符串(避免使用泛型就足够了)
破解某种类型的强制转换以确保在最后得到一个字符串,因为您不信任代码(例如string key=keyobject+“”);
您可能还会浪费时间来决定是否也键入了值。
如果你真的,真的想避免泛型,我至少会在描述返回类型的函数上加个注解。

kh212irz

kh212irz3#

最佳做法是使用 List<Data> . 有一个 Data 与…同班 code , type 以及 id 属性和相应的公共getter/setter,它只是一个表示表的一行的javabean类。哦,您可以将类名“data”更改为实际数据所表示的任何内容。

public class Data {
    private Long code;
    private String type;
    private Long id;
    // Add (or generate) getters/setters here.
}

使用方法如下:

private static List<Data> listData(ResultSet resultSet) throws SQLException {
    List<Data> list = new ArrayList<Data>();
    while (resultSet.next()){
        Data data = new Data();
        data.setId(resultSet.getLong("id"));
        data.setCode(resultSet.getLong("code"));
        data.setType(resultSet.getString("type"));
        list.add(data);
    }
    return list;
}

或者,您也可以使用 Map<Long, Data> 在哪里 Long 键表示 Data 对象。

private static Map<Long, Data> mapData(ResultSet resultSet) throws SQLException {
    Map<Long, Data> map = new HashMap<Long, Data>();
    while (resultSet.next()){
        Data data = new Data();
        data.setId(resultSet.getLong("id"));
        data.setCode(resultSet.getLong("code"));
        data.setType(resultSet.getString("type"));
        map.put(data.getId(), data);
    }
    return map;
}

请注意,我按列名更改了索引,因为使用索引通常表示您正在执行 SELECT * FROM table 并依赖于特定于数据库的列顺序。这是一个糟糕的做法,你实际上应该做一个 SELECT id, code, type FROM table . 我还将修饰符改为 private static 因为在实际中,决不应该将resultset传递到使用它的dao类之外。始终获取并关闭 Connection , Statement 以及 ResultSet 在同一方法块中。
对于如何正确使用基本dao的更多见解,您可能会发现本文也很有用。

pgx2nnw8

pgx2nnw84#

如果代码有r个读取器,需要n毫秒才能意识到m是 Map<String,Object> ,则使用泛型将节省大约r x n毫秒。随着时间的推移,这一点意义重大。另外,您正在向客户机改进doc(使用真实的东西,而不仅仅是javadoc)。

brgchamk

brgchamk5#

主要的好处是对方法的调用者。

public void processData(ResultSet rs) throws SQLException {
     Map m = extractData(rs);
     setType(m.get( ...)); //now what kind of key did that map take again? Have to go look ...
}

这不一定值得(尤其是在稳定的代码中)。我现在正在做这件事,我发现了一些有趣的类型错误的代码。当然,它碰巧没有在生产中出现错误,但那只是等待发生。通过在整个过程中强制使用相同的参数类型,我们能够发现这些潜在的错误。

yi0zb3m4

yi0zb3m46#

问题是我很难找到一个理由来重新写一个“通用”的方式
我不认为有什么令人信服的理由这么做。如果您不是在创建新版本,也不是在修复代码中的错误,我认为您最好关注更相关的部分。
我的意思是,这段代码所属的“应用程序/库/框架/组件/etc”有可能(非常高的可能性)有许多缺陷/问题/增强尚未编码。
我宁愿使用泛型来实现新的功能,也不愿更改这一部分。
如果我做了mapm给我什么“真正”的好处(除了绑定到字符串键)?
到现在为止,完全没有。有些人可能声称可读性,但你多久去看一段代码(引用你的话)“它工作得非常好”
现在,如果这段代码位于当前正在更改的某段代码的中间,或者导致了许多错误,那么您可以重构有问题的组件并在过程中修复它,您将获得编译时检查+可读性。但如果不是这样的话,我会就这样离开。

icomxhvb

icomxhvb7#

类型安全,主要是指编译时的错误检测。
这意味着更好的代码和更好的可维护性,因为将来对代码库的更改不太可能破坏某些东西。
但是:你是否应该重新编写代码是一个只有你能做的决定。
如果现在一切正常,你知道你的用户群(也许只有你;-)他们知道自己在做什么……为什么要投入变革的成本?还要考虑在进行更改时引入新错误和细微错误的可能性(尽管像intellij idea这样的ide支持有[generify]帮助)。

7lrncoxx

7lrncoxx8#

(这与您的问题有关,请稍候)
如果您仔细查看javadocs,您将永远不会(如果我错了,请纠正我)在util之外找到接受或返回集合的方法。
一开始我不明白这一点——他们必须到处使用集合。
问题是,一个集合产生了一个糟糕的api。它是不安全的(您如何保证其他线程不会更改它?如何确保没有人删除关键元素?如何确保它与其他集合/数据/保持同步?)
另外,请注意,您编写的是一个实用函数,而不是一个方法(它不引用成员变量)。这不是oo。当您传递集合时经常会发生这种情况,这通常是oo设计糟糕的一个好迹象(方法在错误的类中)。
如果将结果集传递给包含集合的对象的构造函数,则可以更好地控制这种情况--还可以发现许多其他实用程序函数实际上属于该类。
泛型的问题是,一旦你的集合被包含在一个相当有限的类中,它们就很有趣,但没有那么重要了——当然仍然有用。
如果您打算重构您的集合以使用泛型,那么您可以考虑一直这样做,并创建一个包含泛型的对象。
然后,对泛型本身的重构变得非常简单——非常免费。没有它,泛型几乎只是一个创可贴,在你的设计/安全上留下了巨大的漏洞。

ej83mcc0

ej83mcc09#

您可能对该代码感到满意并理解它—但是对于其他几年后出现并希望维护它的人呢?
任何关于类型的额外帮助在静态类型语言中都很有用。你关于 <String, Object> 是有效的,那么为什么不创建一个强类型的值对象,并使用唯一键将其添加到Map中呢?

o8x7eapl

o8x7eapl10#

它提高了可读性和可维护性。传统上,支持和维护是软件开发中最昂贵的方面。在前面花点时间,希望能为自己省点钱。

相关问题