我们有几个区域可以看到这样的代码
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
钥匙)?
10条答案
按热度按时间sbtkgmzw1#
如果代码可以工作,那么重写代码可能没有什么好处。但是,除了编译时类型检查之外,您可能希望切换到使用泛型的另一个原因是它使代码自文档化。它明确了它所使用的类型。
r7xajy2e2#
好处是,任何调用者都可以假设键是字符串,这不是因为他们熟悉代码,也不是因为他们非常确定自己知道Map是如何构造的,而是因为语言强制执行了Map。值的异构性也被明确指定。
这可能看起来很愚蠢,因为你知道代码已经可以工作了,但是我遇到过这样的情况:你必须将遗留代码或libs集成到一个通用的应用程序中,并且已知类型和未知Map之间的界限非常明显。对于Map的消费者,你要么
假设键是一个字符串(错误的做法)
挖掘源代码(如果可以的话),让自己相信键总是字符串(避免使用泛型就足够了)
破解某种类型的强制转换以确保在最后得到一个字符串,因为您不信任代码(例如string key=keyobject+“”);
您可能还会浪费时间来决定是否也键入了值。
如果你真的,真的想避免泛型,我至少会在描述返回类型的函数上加个注解。
kh212irz3#
最佳做法是使用
List<Data>
. 有一个Data
与…同班code
,type
以及id
属性和相应的公共getter/setter,它只是一个表示表的一行的javabean类。哦,您可以将类名“data”更改为实际数据所表示的任何内容。使用方法如下:
或者,您也可以使用
Map<Long, Data>
在哪里Long
键表示Data
对象。请注意,我按列名更改了索引,因为使用索引通常表示您正在执行
SELECT * FROM table
并依赖于特定于数据库的列顺序。这是一个糟糕的做法,你实际上应该做一个SELECT id, code, type FROM table
. 我还将修饰符改为private static
因为在实际中,决不应该将resultset传递到使用它的dao类之外。始终获取并关闭Connection
,Statement
以及ResultSet
在同一方法块中。对于如何正确使用基本dao的更多见解,您可能会发现本文也很有用。
pgx2nnw84#
如果代码有r个读取器,需要n毫秒才能意识到m是
Map<String,Object>
,则使用泛型将节省大约r x n毫秒。随着时间的推移,这一点意义重大。另外,您正在向客户机改进doc(使用真实的东西,而不仅仅是javadoc)。brgchamk5#
主要的好处是对方法的调用者。
这不一定值得(尤其是在稳定的代码中)。我现在正在做这件事,我发现了一些有趣的类型错误的代码。当然,它碰巧没有在生产中出现错误,但那只是等待发生。通过在整个过程中强制使用相同的参数类型,我们能够发现这些潜在的错误。
yi0zb3m46#
问题是我很难找到一个理由来重新写一个“通用”的方式
我不认为有什么令人信服的理由这么做。如果您不是在创建新版本,也不是在修复代码中的错误,我认为您最好关注更相关的部分。
我的意思是,这段代码所属的“应用程序/库/框架/组件/etc”有可能(非常高的可能性)有许多缺陷/问题/增强尚未编码。
我宁愿使用泛型来实现新的功能,也不愿更改这一部分。
如果我做了mapm给我什么“真正”的好处(除了绑定到字符串键)?
到现在为止,完全没有。有些人可能声称可读性,但你多久去看一段代码(引用你的话)“它工作得非常好”
现在,如果这段代码位于当前正在更改的某段代码的中间,或者导致了许多错误,那么您可以重构有问题的组件并在过程中修复它,您将获得编译时检查+可读性。但如果不是这样的话,我会就这样离开。
icomxhvb7#
类型安全,主要是指编译时的错误检测。
这意味着更好的代码和更好的可维护性,因为将来对代码库的更改不太可能破坏某些东西。
但是:你是否应该重新编写代码是一个只有你能做的决定。
如果现在一切正常,你知道你的用户群(也许只有你;-)他们知道自己在做什么……为什么要投入变革的成本?还要考虑在进行更改时引入新错误和细微错误的可能性(尽管像intellij idea这样的ide支持有[generify]帮助)。
7lrncoxx8#
(这与您的问题有关,请稍候)
如果您仔细查看javadocs,您将永远不会(如果我错了,请纠正我)在util之外找到接受或返回集合的方法。
一开始我不明白这一点——他们必须到处使用集合。
问题是,一个集合产生了一个糟糕的api。它是不安全的(您如何保证其他线程不会更改它?如何确保没有人删除关键元素?如何确保它与其他集合/数据/保持同步?)
另外,请注意,您编写的是一个实用函数,而不是一个方法(它不引用成员变量)。这不是oo。当您传递集合时经常会发生这种情况,这通常是oo设计糟糕的一个好迹象(方法在错误的类中)。
如果将结果集传递给包含集合的对象的构造函数,则可以更好地控制这种情况--还可以发现许多其他实用程序函数实际上属于该类。
泛型的问题是,一旦你的集合被包含在一个相当有限的类中,它们就很有趣,但没有那么重要了——当然仍然有用。
如果您打算重构您的集合以使用泛型,那么您可以考虑一直这样做,并创建一个包含泛型的对象。
然后,对泛型本身的重构变得非常简单——非常免费。没有它,泛型几乎只是一个创可贴,在你的设计/安全上留下了巨大的漏洞。
ej83mcc09#
您可能对该代码感到满意并理解它—但是对于其他几年后出现并希望维护它的人呢?
任何关于类型的额外帮助在静态类型语言中都很有用。你关于
<String, Object>
是有效的,那么为什么不创建一个强类型的值对象,并使用唯一键将其添加到Map中呢?o8x7eapl10#
它提高了可读性和可维护性。传统上,支持和维护是软件开发中最昂贵的方面。在前面花点时间,希望能为自己省点钱。