繁体   English   中英

跟踪前泛型 Java 中的集合中的内容?

[英]Keeping track of what's in a Collection in pre-generics Java?

由于一堆原因(信不信由你)并不像您想象的那么不合理,我们仍然(叹息)使用 Java 1.4 来构建和运行我们的代码(尽管我们计划最终迁移到 Java 7那一年)。

我们现有的使用Collection类的代码并不能很好地说明Collection中的预期内容。 显然,您可以阅读代码并查看最终执行的向下转换并从中推断出什么,但您不能只查看方法声明并知道作为方法参数或方法返回值的Collection object 实际包含什么。

在我正在编写的新代码中以及在使用Collection的旧代码中时,我一直在向Collections声明添加内联注释,以显示如果使用 generics 会声明什么。 例如:

Map/*<String, Set<Integer>>*/ theMap = new HashMap/*<String, Set<Integer>>*/();

或者

List/*<Actions>*/ someMethod(List/*<Job>*/ jobs);

为了与 SO 这里对主观性的皱眉保持一致,而不是问你对此的看法(尽管我承认我想知道——我确实觉得它有点难看,但仍然喜欢那里有类型信息)我会改为只要问一下,如果有的话,你做了什么来明确预泛型Collection对象所持有的内容。

What we recommended back in the old days -- and I was a Java Architect at Sun when Java 1.1 was the New Thing -- was to write a class around the structure (I don't think 1.1 even had Collection as a base class)以便类型转换发生在您控制的代码中,而不是用户代码中。 所以,例如,像

 public class ArrayOfFoo {
     Object [] ary;  // ctor left as exercise

     public void set(int index, Foo value){
         ary[index] = (Object) value; // cast strictly not needed, any Foo is an Object
     }
     public void get(int index){
         return (Foo) ary[index];     // cast needed, not every Object is a Foo
     }
 }

听起来您拥有的代码库不是按照这个约定构建的; 如果你正在编写新代码,你没有理由不能开始。 如果做不到这一点,你的约定还不错,但很容易忘记演员表,然后必须搜索找出为什么你会得到一个糟糕的演员表异常。 通过对名称中的类型进行编码,最好使用匈牙利符号或 Smalltalk 'aVariable' 约定的一些变体,以便您使用

 Object fooAry = new Object[aZillion];

 fooAry[42] = new Foo();
 Foo aFoo = fooAry[42];

使用明确的变量标识符,例如jobListactionListdictionaryMap 如果您关心它们包含的对象的类型,您甚至可以约定始终让 Collection 的标识符提示它包含哪种类型的对象。

内联评论实际上不是那个想法。 当我将 1.5 项目移植回 1.4 时,我就是这样做的(而不是删除类型参数)。 结果很好。

我建议编写测试。 由于各种原因:

  • 无论如何,您应该编写测试!
  • 您可以非常轻松地断言集合成员的类型,以确保您的所有代码路径都将正确的类型添加到集合中
  • 您可以使用测试编写代码,作为如何正确使用集合的“示例”

如果您只需要与 1.4 的二进制兼容性,您可以考虑使用工具将 class 文件降级回 1.4,从而立即开始在 1.6 或 1.7 中开发。 您当然需要避免在 1.4 中不存在的任何 API(不幸的是,您无法使用 generics 针对 1.4 ZBE1587EA25D1C05C81D3BDE9C4C 直接声明任何泛型类型的代码)。 字节码仍然是相同的(至少 1.6,我不确定 1.7)。 一个可以解决问题的免费工具是ProGuard 它可以做更复杂的事情,还可以删除 class 文件中 generics 的所有痕迹。 如果不需要,只需关闭混淆和优化即可。 如果您将 1.4 库提供给它,它还会警告您是否在处理的代码中使用了一些缺失的 API。

我知道这被许多人认为是一种黑客攻击,但我们有类似的要求,我们需要一些代码才能在个人 Java 虚拟机(本质上是 Java 1.1)和其他几个奇异的虚拟机上运行,这种方法效果很好。 我们从 ProGuard 开始,然后为该任务制作了自己的工具,以便能够针对不同 VM 中的一些错误实施一些变通方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM