我最近从Eclipse转为IntelliJ,很快就被介绍到@Contract注释中,我立即喜欢上了这些注释背后的概念(“在调用已注释的方法的方法中查找问题”)。我的第一个想法是使用它们来定义getter和实用工具方法,而pure注释参数似乎符合这一要求:
纯属性用于不更改对象状态但只返回新值的方法。如果不使用其返回值,则移除其调用不会影响程序状态或更改语义,除非方法调用引发异常(异常不被视为副作用)。
然而,我感到困惑的是,上面的话到底是什么意思。
发布于 2019-06-03 13:34:38
一个例子可能是澄清。考虑以下代码:
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,因为它没有副作用。据我所知,没有官方的指导方针。
发布于 2019-06-04 07:17:31
提到的对象是指通过方法参数或类字段传递的对象吗?
同时传递调用方法的实例的对象和字段。
此外,什么可以被限定为更改、更改对象引用、内容,或者两者兼而有之?
两者都有。任何改变都有资格。
在纯方法中调用更改这些对象状态的方法是否违反了约定?
是。杂质是具有传染性的:从另一种方法中调用一种非纯方法,后者也是非纯的。
关键的部分是:
如果不使用其返回值,则移除其调用不会影响程序状态或更改语义,除非方法调用引发异常(异常不被视为副作用)。
撇开异常不谈,另一种看待这个问题的方法是:每当方法内联不改变程序的语义时,该方法都是纯的。
https://stackoverflow.com/questions/56397987
复制相似问题