这两个java变量声明有什么区别?

时间:2010-10-14 18:56:09

标签: java variables set declaration hashset

public class SomeClass {
    private HashSet<SomeObject> contents = new HashSet<SomeObject>();
    private Set<SomeObject> contents2 = new HashSet<SomeObject>();
}

有什么区别?最后他们都是HashSet不是吗?第二个看起来对我来说是错的,但我已经看到它经常使用,接受和工作。

5 个答案:

答案 0 :(得分:22)

Set是一个接口,HashSet是一个实现Set接口的类。

将变量声明为HashSet类型意味着不能使用Set的其他实现。如果您需要HashSet的特定功能,则可能需要此功能。

如果您不需要HashSet中的任何特定功能,最好将变量声明为Set类型。这使得确切的实现可以在以后更改。您可能会发现,对于您正在使用的数据,不同的实现可以更好地工作。通过使用界面,您可以在以后需要时进行此更改。

您可以在此处查看更多详细信息:When should I use an interface in java?

答案 1 :(得分:3)

Set是HashSet实现的集合接口。

第二种选择通常是理想的选择,因为它更通用。

答案 2 :(得分:3)

由于HashSet类实现了Set接口,因此将HashSet分配给Set变量是合法的。但是你不能走另一条路(将一个Set分配给一个更具体的HashSet变量)。

答案 3 :(得分:3)

SetHashSet实现的接口,因此如果您执行此操作:

Set<E> mySet = new HashSet<E>();

您仍然可以访问HashSet的功能,但您也可以灵活地在将来用另一个Set类的实例替换具体实例,例如{{1} }或LinkedHashSet,或其他实现。

第一种方法使用具体类,允许您用自身或子类的实例替换类,但灵活性较低。例如,如果您的变量类型为TreeSet,则无法使用TreeSet

这是约书亚布洛赫Effective Java, 2nd Edition的第52项。

  

通过接口参阅对象

     

...您应该倾向于使用接口而不是类来引用对象。 如果存在适当的接口类型,则应使用接口类型声明参数,返回值,变量和字段。您真正需要引用对象类的唯一时间是在创建它时用构造函数......

     

// 通常很好 - 使用接口作为类型

     

HashSet

     

// 通常为Bad - 使用具体类作为类型!

     

List<T> tlist = new Vector<T>();

这种做法确实带有一些警告 - 如果您想要的实现具有通用接口无法保证的特殊行为,那么您必须相应地记录您的要求。

例如,Vector<T> vec = new Vector<T>();Vector<T>,而synchronized(也是ArrayList<T>的实施者)则没有,所以如果您在设计中需要同步容器(或不),你需要记录下来。

答案 4 :(得分:2)

值得一提的是,界面与具体类规则对于API中公开的类型最为重要,例如。方法参数或返回类型。对于私有字段和变量,它只能确保您不使用具体实现中的任何方法(即HashSet),但它是私有的,所以并不重要。

另一件事是添加另一个类型引用会略微增加编译类的大小。大多数人都不在乎,但这些事情加起来。