2011-11-21 81 views
1

经过一番考虑之后,我在我的应用程序中实现了缓存,基本上,使用包含Class作为关键字(这是对应于特定缓存实体的类,并从摘要AbstractCache继承的类)和具体缓存对象从那个班制成,看起来相当方便。Class as Hashtable key - 这是一个好主意吗?

但是,将Class作为Hashtable键还是应该使用.canonicalName()或类似的东西?

+1

我怀疑使用'Hashtable'作为缓存并不是最好的选择。对于缓存,无论如何你通常需要实现自己的同步。否则'ConcurrenctHashMap'可能是一个更好的选择。 –

+2

除了Peter的评论之外:请参阅Google Guava的Cache实现,该实现提供了并发性和其他一些功能(可选的弱/软引用,统计信息...)。即使你不使用它,Guava也有一个很好的ClassToInstanceMap,它对你很有用。 –

回答

3

如果你永远不需要卸载类,它可能不是一个问题。但是由于需求可能因您的代码运行方式(独立Java应用程序或部署在Web容器,企业服务器等)而异,因此可能不这样做。类加载器泄漏是非常令人讨厌的错误来追踪和解决。

使用规范名称似乎是一个更好的解决方案。但请记住另一个挑战:如果您有多个可能加载相同类的类加载器,那些类仍将被视为不兼容。您将无法通过其规范名称来区分它们,而由不同类加载器加载的两个相同类将产生两个不同的实例,并且可以在同一个映射中用作键。

如果您没有非常具体的类加载器约束或要求,请使用规范名称。如果您正在部署除独立Java应用程序之外的其他任何应用程序,请谨慎行事。

+1

我仍然会使用Class对象。由于不兼容的类导致的ClassCastExceptions可能比classloader泄漏更糟糕,所以最好在这一边。此外,如果您将该类的实例作为值存储在该缓存中,那么使用规范名称将无助于班级卸载,因为无论如何您都需要从地图中删除条目。如果你需要这个,使用弱/软引用键和值。 –

+0

@PhilippWendler很好的建议。我只记得我曾经需要一个class-to-something的地图,并且使用'Class'对象而不是名字。提供了一些方法从缓存中刷新类,以防需要卸载。 –

2

听起来很好。我过去曾经这样做过。类实际上是不可变的单例,所以没有机会使用类的“错误”实例。

唯一会遇到问题的是如果涉及多个ClassLoader,但在大多数应用程序中这种情况很少。

相关问题