我正在阅读此网站的教程。http://tutorials.jenkov.com/java-unit-testing/matchers.html
我相信作者非常有经验。我看到这样的代码。我还看到其他人总是喜欢将方法的参数分配给变量,然后在方法中使用它。这是这一行。 protected Object theExpected = expected;
任何人都可以告诉我,这种编码风格有什么好处?这是试图避免对象状态被改变还是什么?
如果参数不是Object而是原始变量,该怎么办?
如果它是一个像String这样的不可变对象怎么办?谢谢。
public static Matcher matches(final Object expected){
return new BaseMatcher() {
protected Object theExpected = expected;
public boolean matches(Object o) {
return theExpected.equals(o);
}
public void describeTo(Description description) {
description.appendText(theExpected.toString());
}
};
}
以下是更新
我刚做了另一个测试,看看在得到对象后这个参数是否仍然可以访问。
package myTest;
public class ParameterAssignTest {
public static void main(String[] args) {
MyInterface myClass = GetMyClass("Here we go");
System.out.println(myClass.getValue());
System.out.println(myClass.getParameter());
}
public static MyInterface GetMyClass(final String myString){
return new MyInterface() {
protected String stringInside = myString;
@Override
public String getValue() {
return stringInside;
}
@Override
public String getParameter() {
return myString;
}
};
}
}
输出:
Here we go
Here we go
这是否意味着即使我们将此参数分配给它仍然有效的局部变量?
答案 0 :(得分:2)
我不相信分配给theExpected
可以实现任何目标。
正如预期的那样,它可以在匿名类中访问。如果它直接在describeTo
中使用,则对象不会是GC,并且当声明expected
的本地范围被保留时,引用仍然有效。
您链接的帖子的作者可能认为这种显式风格更具可读性。
答案 1 :(得分:1)
theExpected
是原始的还是Object(尽管在这个例子中它是一个Object),以及它是否可变是无关紧要的。
matches
方法返回扩展BaseMatcher
的匿名类的实例(并实现Matcher
接口,假设它是一个接口)。
一旦它返回实例,传递给它的局部变量 - expected
- 超出范围,但theExpected
成员,包含与该局部变量相同的值,保持在实例,并且可以由该实例的方法使用。
答案 2 :(得分:1)
如果您希望/需要在内部类中使用局部变量(在本例中为匿名本地类),则必须将该变量声明为final
,无论它是原始类型还是引用类型。这里有更好的解释:Why Java inner classes require "final" outer instance variables?。引用最好的解释IMO:
语言坚持的原因是它为了让你的内部类函数能够访问他们渴望的局部变量而作弊。运行时制作本地执行上下文的副本(以及适当的等等),因此它坚持让你把所有内容都做到最终,这样就可以保持诚实。
如果没有这样做,那么在构造对象之后但在内部类函数运行之前更改局部变量值的代码可能会令人困惑和奇怪。
在这种情况下,似乎作者希望保留一个参数的副本,该参数在生成的匿名类的引用中发送给方法以供进一步评估。一旦方法完成执行,参数Object expected
就不再可用了,所以如果你想/需要保留它,那么你必须将它分配到你的类的一个字段中。