gpt4 book ai didi

HashSet 或其他实现的 Java 变量类型集合?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:42:53 27 4
gpt4 key购买 nike

我经常看到类似 List<String> list = new ArrayList<>(); 的声明或 Set<String> set = new HashSet<>();对于类中的字段。对我来说,使用变量类型的接口(interface)来提供实现的灵 active 是非常有意义的。上面的例子仍然定义了哪种 Collection必须分别使用 s ,分别允许哪些操作以及在某些情况下它应该如何表现(由于文档)。

现在考虑实际上只有 Collection 的功能的情况。 (甚至 Iterable )接口(interface)需要使用类中的字段和 Collection 的种类实际上并不重要,或者我不想过度指定它。所以我选择例如HashSet作为实现并将该字段声明为 Collection<String> collection = new HashSet<>(); .

那么该字段实际上应该是 Set 类型吗?在这种情况下?这种声明是不是不好的做法,如果是,为什么?或者尽可能少地指定实际类型(并仍然提供所有必需的方法)是一种很好的做法。我问这个的原因是因为我几乎没有见过这样的声明,最近我在我只需要指定 Collection 的功能的情况下得到了更多。界面。

例子:

// Only need Collection features, but decided to use a LinkedList
private final Collection<Listener> registeredListeners = new LinkedList<>();

public void init() {
ExampleListener listener = new ExampleListener();
registerListenerSomewhere(listener);
registeredListeners.add(listener);
listener = new ExampleListener();
registerListenerSomewhere(listener);
registeredListeners.add(listener);
}

public void reset() {
for (Listener listener : registeredListeners) {
unregisterListenerSomewhere(listener);
}

registeredListeners.clear();
}

最佳答案

由于您的示例使用私有(private)字段,因此隐藏实现类型并不重要。您(或维护此类的任何人)可以随时查看字段的初始值设定项以了解它是什么。

但是,根据它的使用方式,可能值得为该字段声明一个更具体的接口(interface)。将其声明为 List表示允许重复并且排序很重要。将其声明为 Set表示不允许重复并且排序不重要。如果有一些重要的东西,您甚至可以声明该字段具有特定的实现类。例如,将其声明为 LinkedHashSet表示不允许重复,但排序很重要。

如果类型出现在类的公共(public) API 中,以及对此类的兼容性约束是什么,则选择是否使用接口(interface)以及使用什么接口(interface)变得更加重要。例如,假设有一个方法

public ??? getRegisteredListeners() {
return ...
}

现在返回类型的选择会影响其他类。如果您可以更改所有调用者,也许没什么大不了的,您只需要编辑其他文件即可。但是假设调用者是一个您无法控制的应用程序。现在接口(interface)的选择至关重要,因为您无法在不破坏应用程序的情况下更改它。这里的规则通常是选择支持您期望调用者想要执行的操作的最抽象的接口(interface)。

大多数 Java SE API 返回 Collection .这为底层实现提供了相当程度的抽象,但它也为调用者提供了一组合理的操作。调用者可以迭代、获取大小、进行包含检查或将所有元素复制到另一个集合。

一些代码库使用 Iterable作为最抽象的接口(interface)返回。它所做的只是允许调用者进行迭代。有时这就是全部必要的,但与 Collection 相比可能有些限制。 .

另一种选择是返回 Stream .如果您认为调用者可能想要使用流的操作(例如过滤器、映射、查找等)而不是迭代或使用集合操作,这将很有帮助。

请注意,如果您选择返回 CollectionIterable ,您需要确保返回不可修改的 View 或制作防御性副本。否则,调用者可能会修改您的类的内部数据,这可能会导致错误。 (是的,即使是 Iterable 也可以允许修改!考虑获取一个 Iterator 然后调用 remove() 方法。)如果你返回一个 Stream ,您无需担心,因为您不能使用 Stream修改底层源。

请注意,我将您关于字段声明的问题变成了关于方法返回类型声明的问题。有一种“编程到接口(interface)”的想法在 Java 中非常流行。在我看来,局部变量并不重要(这就是为什么通常可以使用 var ),而对于私有(private)字段则无关紧要,因为那些(几乎)根据定义只影响它们所在的类重新声明。但是,“编程到接口(interface)”原则对于 API 签名非常重要,因此在这些情况下,您确实需要考虑接口(interface)类型。私有(private)领域,不是那么多。

(最后一点:在某些情况下,您需要关注私有(private)字段的类型,那就是当您使用直接操作私有(private)字段的反射框架时。在这种情况下,您需要将这些字段视为是公开的——就像方法返回类型一样——即使它们没有被声明 public 。)

关于HashSet 或其他实现的 Java 变量类型集合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55601504/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com