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中,方法是面向对象的构造,而实例变量是严格意义上的实现细节。在大多数较新的语言中,"实例变量"已被称为"属性"的高级结构所取代;