首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >理解纯粹的方法“契约”

理解纯粹的方法“契约”
EN

Stack Overflow用户
提问于 2019-05-31 15:35:31
回答 2查看 1.3K关注 0票数 1

我最近从Eclipse转为IntelliJ,很快就被介绍到@Contract注释中,我立即喜欢上了这些注释背后的概念(“在调用已注释的方法的方法中查找问题”)。我的第一个想法是使用它们来定义getter和实用工具方法,而pure注释参数似乎符合这一要求:

纯属性用于不更改对象状态但只返回新值的方法。如果不使用其返回值,则移除其调用不会影响程序状态或更改语义,除非方法调用引发异常(异常不被视为副作用)。

然而,我感到困惑的是,上面的话到底是什么意思。

  • 提到的对象是指通过方法参数或类字段传递的对象吗?此外,什么可以被限定为更改、更改对象引用、内容,或者两者兼而有之?
  • 在纯方法中调用更改这些对象状态的方法是否违反了约定?类似于调用构造函数的构建器方法。
  • 客观地认为将方法标记为纯的最佳实践是什么时候?我知道这似乎是一个主观的问题,但必须制定社区指南(可供参考)来确定何时这样做。
EN

回答 2

Stack Overflow用户

发布于 2019-06-03 13:34:38

一个例子可能是澄清。考虑以下代码:

代码语言:javascript
复制
class X {
  public void main(String[] ss) {
    ss[0].toUpperCase(java.util.Locale.ENGLISH);
  }
}

String.toUpperCase()调用不改变被调用的对象ss[0],也不更改提供的参数java.util.Locale.ENGLISH。它返回一个新对象,但代码中不使用该对象。调用不会更改程序中使用的任何对象的状态。因此,删除调用不会改变程序的行为。(严格地说,它将运行得更快,但这不被认为是语义上的相关更改。)

注意,当使用空数组调用main方法时,它将抛出一个异常。当调用被删除时,这将不会发生。但是,对于@Contract注释而言,异常并不被视为副作用。异常可视为一种类型的返回值。

因此,可以将String.toUpperCase()方法注释为纯方法。纯方法在IntelliJ的许多地方都是专门处理的。例如,如果未使用的变量是由纯方法初始化的,则快速修复程序“知道”在删除变量时可以安全地删除初始化器。

Getter通常是纯的,void方法通常不是。但是也有例外,例如,junit.framework.Assert.fail()void,但是是pure,因为它没有副作用。据我所知,没有官方的指导方针。

票数 3
EN

Stack Overflow用户

发布于 2019-06-04 07:17:31

提到的对象是指通过方法参数或类字段传递的对象吗?

同时传递调用方法的实例的对象和字段。

此外,什么可以被限定为更改、更改对象引用、内容,或者两者兼而有之?

两者都有。任何改变都有资格。

在纯方法中调用更改这些对象状态的方法是否违反了约定?

是。杂质是具有传染性的:从另一种方法中调用一种非纯方法,后者也是非纯的。

关键的部分是:

如果不使用其返回值,则移除其调用不会影响程序状态或更改语义,除非方法调用引发异常(异常不被视为副作用)。

撇开异常不谈,另一种看待这个问题的方法是:每当方法内联不改变程序的语义时,该方法都是纯的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56397987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档