今天看到几个类似的问题 - 让我思考:
何时使用泛型有什么规则?
对于您应该问自己的问题似乎没有达成共识,以确定您是否应该使用泛型。这纯粹是一个自以为是的决定吗?
当你不应该使用泛型时更容易问?
答案 0 :(得分:4)
在回到子弹列表的第一点之前,让我先谈谈关于泛型和类型信息的一些一般性观点。
在介绍仿制药之前你还记得Java吗?在任何地方都使用了类型转换。
这就是类型转换本质上是:你告诉编译器有关对象的类型,因为编译器不知道或不能推断它。
类型转换的问题在于你有时会犯错误。您可以向编译器建议类Fiddle
的实例是Frobble
((Frobble)fiddle
),编译器会很乐意相信您并编译您的源代码。但如果事实证明你错了,那么你以后会得到一个很好的运行时错误。
泛型是让编译器保留类型信息的一种不同的,通常更安全的方法。基本上,编译器输入错误的可能性低于人类程序员...... 所需的类型转换越少,潜在的错误来源就越少!一旦确定列表只能包含Fiddle
个对象(List<Fiddle>
),编译器将保留此信息并防止您必须将该列表中的每个项目类型转换为某种类型。 (你仍然可以将一个列表项强制转换为Frobble
,但是为什么你现在编译器让你知道该项是Fiddle
!)
我发现泛型大大减少了对类型转换的需求,因此大量类型转换的存在 - 特别是当你总是转换为相同的类型时 - 可能是泛型应该是的指标反而用了。
让编译器保留尽可能多的类型信息是一件好事,因为输入错误可以在之前发现(在编译时而不是在运行时)。
java.lang.Object
类型的替代品: 在泛型之前,如果你想编写一个处理任何类型的方法,你就使用了java.lang.Object
超类型,因为每个类都是从它派生的。
泛型允许您编写适用于任何类型的方法,但不会强迫您或编译器丢弃已知的类型信息 - 这正是您将对象强制转换为{{{ 1}}类型。因此,经常使用Object
类型可能是泛型可能适当的另一个指标。
何时涉及集合?
为什么仿制药似乎特别适合收藏?因为,根据上述推理,很少允许集合包含任何类型的对象。如果是这样,则Object
类型将是合适的,因为它不对集合施加任何限制。但是,通常情况下,您希望集合中的所有项目(至少)为Object
(或其他类型),如果您让编译器知道,它会有所帮助。泛型是如何做到这一点的方式。
关系是否是该类的组合/聚合?
您已与another question相关联,询问Frobble
属性class Person
应该是car
的通用属性。
在这种情况下,这取决于你的程序是否需要区分本田人和欧宝人。通过使这样的class Person<T extends ICar>
类具有通用性,您基本上可以介绍不同类型的人的可能性。如果这实际上解决了代码中的问题,那就去吧。但是,如果它只引入了障碍和困难,那么就要抵制这种冲动并坚持你的非通用Person
类。
侧节点:请记住,您不必将整个类设为通用;你只能制作一些通用的特定方法。至少在.NET生态系统中,建议尽可能将泛型保持为“本地”,即当只有一个方法通用时,不要将类转换为通用类。
答案 1 :(得分:2)
当满足以下三个条件时,我发现自己使用泛型:
<T extends Bar>
)。 通常在满足这些标准时,会涉及某种Collection
,但不一定。
答案 2 :(得分:0)
在我看来,第二个陈述(何时不使用它们)是正确的。
何时不使用泛型:当强类型过于严格时(通常是泛型中的泛型)。在某些情况下,您希望确保组件之间的松散耦合,并且要点“向我发送您想要的内容,API会以某种方式处理它”,而不是使用某种访问者,而不是指定使用某种泛型类型完成具体的API。
当你应该:如果你没有,你必须将变量强制转换为某种类型(你甚至可能需要猜测或使用instanceof)......
只是一个旁注:每种结构化类型都是某种集合......
答案 3 :(得分:0)
当你不应该使用泛型时更容易问?
要回答这个问题,泛型的一个主要问题是它对Checked Exceptions的处理。以下是Geotz关于此问题的文章。
您应该考虑泛型的原因,同样有information shared的缓存。