用于存储简单数据的“公共静态”和“私有静态”之间的区别。啥是更好的? [复制]

Posted

技术标签:

【中文标题】用于存储简单数据的“公共静态”和“私有静态”之间的区别。啥是更好的? [复制]【英文标题】:Difference between "public static" and "private static" for storing simple data. What is better? [duplicate]用于存储简单数据的“公共静态”和“私有静态”之间的区别。什么是更好的? [复制] 【发布时间】:2017-06-30 00:47:42 【问题描述】:

什么是更好的解决方案?

我在想,实际上哪个性能更好,或者哪个更“正确”?

public static List<String> globalUseVariable;

private static List<String> globalUseVariable;
public static List<String> getGlobalUseVariable() 
    return globalUseVariable;

我认为第二个是因为封装规则?

【问题讨论】:

您可能应该将其设为final,但这是一个见仁见智的问题。性能没有差异(实际上)(方法调用稍微慢)。 有人不得不说,正确的解决方案是没有有全局状态变量。我相信这里的答案总结了一切:***.com/questions/7026507/… 您还需要考虑是否要允许此列表的使用者对其进行修改。如果不是,您可能想要分发一个副本或一个不可变的包装器。副本的优点是您不需要关心并发修改。但是,这一切都取决于上下文是否需要或开销。当然也要避免像害虫一样的static @eckes 是的,这对我来说很有意义! @GhostCat 我不同意 dup 锤子。 【参考方案1】:

简单地说:

首先避免静态 也避免暴露内部状态

拥有 public 可写字段几乎是不可能的。如果您允许多个组件更新该数据,则会导致直接的硬耦合。这也意味着您可以(很可能)对线程安全说“再见”。即使你认为“我今天只会阅读那个领域”;也许你会在几周内忘记这一点。或者你团队中的其他人错过了那部分。所以

所以,如果您有好的理由向“公众”提供一些数据;然后至少使用getter方法;因为这允许(以后)更改。或者它允许简单的增强功能,例如返回内部状态的副本/克隆(以防止“外部人员”稍后操纵该内部状态)。

两种绕过静态的方法:

    如果您真的需要 全局 状态,或者其他东西可以完成这项工作,请仔细考虑 如果您需要全局状态,那么:A) 创建一个接口,表示您要提供的服务 B) 创建该接口的实现作为“普通”类 C) 然后使用实现该接口的单例(例如枚举)[现在单例枚举可以将其工作委托给该 impl 类]

通过遵循方法 2,您将获得具有相同功能的东西(您拥有所有代码都可以使用的“全局”东西);但是你让事情变得更加解耦;最重要的是:您可以在各处进行合理的单元测试。

静态通常是合理单元测试的“杀手”。

【讨论】:

【参考方案2】:

建议使用 getter,因为您可能希望在不更改 API 的情况下对类进行更改,或者您会决定在返回列表之前执行某种类型的转换。看看this answer regarding a similar situation。在我看来,同样的原则通常适用于静态字段,真的没有理由为它们例外。 This question 也涉及到同样的话题。我认为那里列出的原因也适用于静态字段并且是完全合理的。

一般而言,如果您将某些内容公开,您将创建一个公共 API,并应保证它不太可能更改,以免日后让您头疼(如果您正在创建公共库并且必须更改,甚至可能无法更改)向后兼容)。

另外使用 getter 和 setter,您可以确保您编写的代码是线程安全的,如其他答案和链接问题中所述。当您公开公共字段时,您无能为力。

【讨论】:

我们在这里谈论的是static getters。 我会考虑删除 getter 和 setter 的唯一情况是,如果我们正在讨论存储在 final 字段中的某种配置值,并且您真的不想使用 getter某种原因(我猜是为了让它包含更少的代码,但我不会亲自去做)。链接问题中提到的所有原因同样适用于静态字段。 只是一个提示:关于垂直间距的新疯狂概念(老派称之为“段落”)有助于使您的内容更易于阅读。只是说... @boreq 如果类外的代码可以修改List,那么getter 的意义何在。看我的回答。 重点是 getter 不必返回那个特定的列表。将来您可能希望更改它以完全返回其他内容。这通常是一个破坏性的 API 更改,这是在非常大的代码库或库中无法完成的。正如我所说,线程安全或防止列表被复制是由该问题解决的其他问题。不使用吸气剂确实是一种不好的做法,至少在我看来,如果您查看我链接的答案,其他人似乎同意我的观点。【参考方案3】:

哪个更“正确”?

就您的代码而言,我都不同意。将List 标记为private,然后在方法中返回对相同List 的引用,您将一无所获。您不能调用此封装,因为无论您在方法中添加什么逻辑,您都会将 List 引用返回给调用者,以便他们随意修改。如果你想真正遵守封装,你至少可以要求你的方法返回一个不可修改的集合(使用Collections.unmodifiableList)。

如果您希望您的列表为public,您至少可以将其标记为final,以便您的类外的代码无法尝试类似YourClass.globalUseVariable=null 的操作并破坏任何使用List 的代码。

【讨论】:

以上是关于用于存储简单数据的“公共静态”和“私有静态”之间的区别。啥是更好的? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

什么时候应该使用公共静态方法

java 多线程-单例模式

覆盖(非)静态类中的私有方法

超类中的私有final可以被覆盖吗?

PHP设计模式-单例模式

PHP面向对象单例模式(懒汉式)