跟踪pre-generics Java中Collection中的内容?

时间:2011-05-27 21:02:00

标签: java generics commenting

由于一系列原因(不管你信不信)并不像你想象的那么糟糕,我们仍然(叹气)使用Java 1.4来构建和运行我们的代码(虽然我们计划最终在年底之前转向Java 7。

我们使用Collection类的现有代码并没有很好地说明Collection中预期的内容。显然,您可以阅读代码并查看最终结束的内容并从中推断,但您不能只查看方法声明并知道作为方法参数或方法返回的Collection对象是什么价值确实存在。

在我正在编写的新代码中以及当我使用Collection s的旧代码时,我一直在向Collections声明添加内联注释以显示已声明的内容如果使用仿制药。例如:

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

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

与SO在这里对主观性的皱眉一致,而不是问你对此的看法(虽然我很想知道 - 我觉得它有点难看,但仍然喜欢那里的类型信息)我相反,只要问一下你做了什么,以便明确前仿制药Collection对象所持有的东西。

4 个答案:

答案 0 :(得分:4)

我们过去推荐的东西 - 当Java 1.1是New Thing时,我是Sun的Java架构师 - 是围绕结构写一个类(我不认为1.1甚至将Collection作为一个基类)以便在您控制的代码中而不是在用户代码中使用类型转换。所以,例如,像

这样的东西
 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];

答案 1 :(得分:1)

使用明确的变量标识符,例如jobListactionListdictionaryMap。如果你关心它们包含的对象的类型,你甚至可以使它成为一个约定,总是让Collection的标识符暗示它所拥有的对象类型。

内联评论实际上不是那个想法。当我将1.5项目移植回1.4时,我做到了(而不是删除类型参数)。它运作得很好。

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

如果您只需要与1.4的二进制兼容性,您可以考虑使用工具将类文件降级回1.4,从而立即开始在1.6或1.7中开发。您当然需要避免1.4中没有的任何API(遗憾的是,您不能直接使用泛型编译1.4 jar的代码,因为它们没有声明任何泛型类型)。字节码仍然是相同的(至少1.6,我不确定1.7)。一个可以解决问题的免费工具是ProGuard。它可以做更复杂的事情,也可以删除类文件中的所有泛型痕迹。如果您不需要,请关闭模糊处理和优化。如果你在1.4库中提供了一些缺失的API,它也会警告你。

我知道这被许多人视为黑客,但是我们有类似的要求,我们需要一些代码仍然可以运行在个人Java VM(这实际上是Java 1.1)和其他几个奇特的虚拟机上,这种方法非常有用好。我们从ProGuard开始,然后使用我们自己的工具完成任务,以便为不同虚拟机中的一些错误实现一些变通方法。