为什么这是一个很好的做法,使最后一个字段指向一个不可变的对象非公共?



effective Java有一个关于访问控制的声明:即使一个字段是final的,并且引用一个不可变对象,通过将其公开,您放弃了切换到新的内部数据表示的灵活性,其中字段不存在。

我不明白这是什么意思。如果有人能解释一下,我将不胜感激。

与Kotlin和Scala等较新的语言不同,Java在字段和方法之间有非常明确的区别。如果你有一个

public final Foo foo;

那么它总是指向内存中的实际字段。它永远不能是一个方法,也永远不能运行任意代码。调用myInstance.foo总是直接访问内存,这与OOP原则是相反的。当我向实例请求某事时,应该由实例决定如何处理该请求,而不是我的。

在Kotlin中,属性可以有getter和setter,所以即使我们有看起来像字段的东西,它也可能调用一个方法来访问它。这使我们能够提前验证我们的代码。现在我们可以实现一个实际的实例变量

val foo: Foo = myConcreteInstance()

然后,当foo需要进行数据库查询或其他事情时因为我们要扩展应用程序,我们可以改变实现

val foo: Foo
get() = loadFooLazily()
private fun loadFooLazily(): Foo {
// Some complicated code ...
}

至关重要的是,这会影响下游nobody。下游的其他人仍然编写myInstance.foo并使用新代码。这不是一个突破性的变化。

我们不能在Java中这样做。myInstance.foo总是一个变量,而不是一个方法。因此,Effective Java建议始终通过方法访问实例变量,以便将来使用。如果我们写

private final Foo foo;
public Foo getFoo() {
return foo;
}

然后我们可以在不破坏其他代码的情况下更改getFoo。这是理念上的不同:在Java中,方法是面向对象的构造,而实例变量是严格意义上的实现细节。在大多数较新的语言中,"实例变量"已被称为"属性"的高级结构所取代;

最新更新