如何识别哪些类型可以生成?

时间:2013-02-20 18:30:54

标签: java generics

我知道基于对象的集合是通用化的主要候选者,并且已经在集合库中进行了泛化。除了类或界面应具备哪些属性和行为以使其成为一般化的候选者之外?为什么例如ThreadLocal类或AtomicReference类被广泛化?导致这一设计决定的原因是什么?

5 个答案:

答案 0 :(得分:3)

需要为不同类型重用的类始终是泛化的候选者。 例如class Pair<U,V>

答案 1 :(得分:3)

如果一个类可以与各种其他类具有相同的关系,那么该类是一个很好的候选者。集合类是通用的,因为关系“包含”可以应用于任何类对象。 ComparableComparator接口是通用的,因为“可以与之比较”的关系可以应用于许多不同的对象(尽管实际上这仅限于类的自身层次结构中及其周围的对象{{1} })。

此外,如果您发现自己编写了多个非常相似的类,唯一的区别是您正在操作的对象的类型,那么请考虑编写一个通用的类。

修改

使用内置类ComparableAtomicReference,“包含”关系适用于各种对象类型。 ThreadLocalAtomicReference对象仍包含另一种类型的对象。这允许以类型安全的方式设置和返回特定类型,而无需使用“get”和“set”方法返回/获取ThreadLocal,并且无需转换返回类型在调用“get”方法时。该关系适用于特定类型,但在类设计时不需要知道确切类型。

编辑2:

我认为制作类通用的大多数示例都涉及“包含”关系。但是,这只是泛型关系的一个特定示例,即使Collections框架基于“contains”关系,它也提供了许多“包含”的类。一般关系不一定是“包含”,所以我将尝试举例说明哪些内容可以通用,但关系是“包含”。

想象一个抽象的Object类,具有诸如ShapeLineSquare等具体类。现在我们定义知道的接口Circle如何画形状。这里的关系是“吸引”。我们可以定义界面:

ShapeDrawer

现在我们需要专门针对特定形状的public interface ShapeDrawer { public void drawShape(Shape shape); } 的具体具体实现,例如ShapeDrawerCircleDrawer

SquareDrawer

现在,public class CircleDrawer implements ShapeDrawer { public void drawShape(Shape shape) {/*...*/} } 中的drawShape方法必须先测试CircleDrawer shape以查看它是否为Circle

现在,使用泛型的解决方案:

public interface ShapeDrawer<T extends Shape> {
   public void drawShape(T shape);
}

现在,实现可以绘制特定的Shape

public class CircleDrawer implements ShapeDrawer<Circle> {
    public void drawShape(Circle circle) {/*...*/}
}

答案 2 :(得分:1)

数据结构应该是通用的,因为结构应该能够处理多种类型的输入。

任何可以/应该由多种数据类型使用的类都应该以通用方式创建。

答案 3 :(得分:1)

不要寻找“凝聚”的东西。相反,您应该使用泛型以您认为最合适的方式完成特定任务。泛型只是工具箱中用来完成任务的工具。

如果你的问题是什么样的事情可能是最好的一般实施,那么你自己的例子是一个主要的例子。当您需要以类似的方式处理不同的结构(如列表)时,泛型是一个很好的解决方案。这包括大多数以类不变的方式处理其他类的类,或者对类的子部分不变的类。

答案 4 :(得分:1)

每当你发现自己投射一个值时,你应该考虑是否允许你删除该投射。让我们举例,ThreadLocalAtomicReference。使用get()返回的值的两次都需要强制转换(至少大部分时间)。

请记住,仿制药可能非常嘈杂。权衡成本和收益。特别要考虑的是,通用化是对API用户有利还是仅仅对实施者有利。