java - 使无副作用的方法静态化

标签 java static

几天前我做了一次代码审查,我注意到引入了几个static方法。当我与打开拉取请求的同事交谈时,他告诉我他使无副作用 ( not pure ) 方法 static 因为它有助于处理副作用。他表示,通过这种方式,您可以很容易地看出哪些方法会导致副作用,哪些不会。

就我个人而言,我不同意这一点。尽管有许多 static 方法会导致副作用(看看 System ),static 方法经常(不总是)导致问题,因为测试期间的实例。

但是,static 本身并不坏,而且我知道每一天都是上学日。这是我缺少的模式吗?使无副作用的方法 static 有什么好处?

最佳答案

static 方法与副作用的关注只是间接相关。在私有(private)方法的情况下,如果它不取消引用 this,则可以将其设置为 static许多 结果之一是这样的方法不会改变对象的状态,这排除了一小部分副作用。不要忘记该方法也可以接受参数并改变它们;即使没有它,它也始终可以访问和/或改变可通过某些静态变量访问的全局状态。

真正的决策标准是:

  1. 方法是否取消引用 this
  2. 方法是否根据this 的类型进行动态分派(dispatch)?

如果两个问题的答案都是“否”,那么该方法可以安全地变为static

关于“静态方法给测试带来问题”的提示与上面的 2. 有关。在测试中,我们有时必须提供方法的模拟覆盖。在那种情况下,对 2. 的回答是"is",并且该方法不符合标准。

如果可以,私有(private)方法应该始终是静态的。在注意到 static 标记的瞬间,您将获得以下重要知识:该方法不处理对象的状态,也不调用任何其他实例方法。

如果一个公共(public)方法满足成为static 的标准,那么它很可能甚至不属于它所在的类,因为它与它没有耦合。在大多数情况下,此类方法是重定位到静态实用程序类的候选方法。

最后, 函数(相对于无副作用)的概念在这里很重要:纯函数最不可能需要模拟。它们通常执行起来简单且快速,并且只需提供适当的输入即可控制其结果。比较这两种方法:

  • System.currentTimeMillis()——无副作用,但依赖于全局状态,其输出无法控制。通常,它不可模拟的事实意味着在测试变得不可重复时会遇到麻烦。
  • Character.toUpperCase(char)——一个纯函数,执行简单的转换。你永远不必 mock 这个。

关于java - 使无副作用的方法静态化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39614870/

相关文章:

java - 在 Web 服务中使用 OAuth 时出现异常

java - ArrayList中的HashMap在循环之外不存在

c++ - 如果在堆上定义,QProcess不会终止/终止进程

java - OpenGL 在 Android 2.3.7(CyanogenMod-7) 上绑定(bind)空白纹理,而在其他 Android 版本上绑定(bind)实际图像

java - 从 context.xml 加载 Bean 属性值

java - Hibernate Fetch 不再是 Join 的子类型

java - 直接调用子类对象时的静态和私有(private)方法行为听起来像重写?

java - 为什么需要静态修饰符以及如何修复它?

java - 继承中的静态变量

java - 为什么super可以访问父类(super class)的非静态变量?