【发布时间】:2019-06-22 22:13:57
【问题描述】:
我已经开始学习 Kotlin。我目前的背景是Java。我发现 Kotlin 中的类属性与 Java 中的类字段有很大不同,尽管它们看起来很相似。在他的问题中,我想汇总这两者之间的所有技术差异。这是我已经想通的:
Java 字段和隐藏 vs Kotli 属性和覆盖
(实际上这促使我写这篇文章):
在Java中,基类的字段被派生类中的同名字段隐藏,因此使用哪个字段取决于对包含该字段的对象的引用类型,而不是对象本身(字段不会像方法那样被覆盖,因此它们不依赖于对象的运行时类型)。例如这段代码:
class A {
public String name = "A";
public void printMessage() {
System.out.println("Field accessed in method declared inside class A invoked form an object of " + getClass() + " : " + name);
}
}
class B extends A{
public String name = "B";
}
public class Main {
public static void main(String... args){
B b = new B();
System.out.println("Field from instance of class B pointed by reference to B : " + b.name);
A a = b;
System.out.println("Field from instance of class B pointed by reference to A : "+a.name);
a.printMessage();
}
}
打印这个:
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : A
Field accessed in method declared inside class A invoked form an object of class B : A
相比之下,Kotlin 属性是由自动生成的 getter 和 setter 访问的字段。属性被覆盖(不是隐藏),所以属性访问是在运行时解析的,和上面含义相似的代码用 Kotlin 编写:
open class A {
open val name = "A"
fun printMessage() {
println("Field accessed in method declared inside class A invoked form an object of $javaClass : $name")
}
}
class B(override val name : String = "B") : A()
fun main(args : Array<String>) {
val b : B = B()
println("Field from instance of class B pointed by reference to B : " + b.name)
val a : A = b;
println("Field from instance of class B pointed by reference to A : " + a.name)
a.printMessage()
}
打印这个:
Field from instance of class B pointed by reference to B : B
Field from instance of class B pointed by reference to A : B
Field accessed in method declared inside class A invoked form an object of class B : B
访问级别
Java 字段是包的——默认情况下是私有的。 Kotlin 属性默认是公开的。
默认初始化
Java 字段使用合理的默认值进行初始化(如此处所述:https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html)。
每个 Kotlin 类属性的创建方式都必须允许它在访问时提供明确的给定值。 可以通过初始化器、构造器、设置器、延迟初始化来实现这一点:
class InitValues(val inCtor : String = "Given in constructor"){
var byInitializer = "In initializer"
var initializedWithNull : String? = null
val valueGivenByGetter
get() : String {
return "This value is given by getter"
}
val byLazyInit : String by lazy { "This is lazy init" }
}
但必须给出应该返回的值——不会提供默认值。
在类字段/属性方面是否还有其他技术差异可能会让 Java 程序员在 Kotlin 中编写代码感到惊讶?
(我不是在谈论附加功能,例如委托属性,而是那些乍一看类似于 Java 中存在的东西并且可能是欺骗性的东西)
【问题讨论】:
-
对于有Java背景和学习Kotlin的人来说,这个比较真的很有用,谢谢!
标签: java kotlin properties field