Firestore 的“documentSnapshot.toObject(className::class.java)”如何重新分配在主构造函数中设置的“val”值?
How does Firestore's `documentSnapshot.toObject(className::class.java)` reassign `val` values that were set in the primary constructor?
我一直在开发 Kotlin 后端服务,偶然发现了 Firestore documentSnapshot.toObject(className::class.java)
方法。
采用以下 Kotlin data class
:
data class Record(
val firstName: String = "",
val lastName: String = "",
val city: String = "",
val country: String = "",
val email: String = "")
以及我的 Repository
class 中的以下代码:
if (documentSnapshot.exists()) {
return documentSnapshot.toObject(Record::class.java)!!
}
现在,据我了解,方法 documentSnapshot.toObject(className::class.java)
需要并调用无参数默认构造函数,例如val record = Record()
。
此调用将调用主构造函数并将其中声明的默认值(在数据 class Record
、空字符串 ""
的情况下)分配给字段.
然后,它使用 public setter 方法将实例的字段设置为在 document
.
中找到的值
假设字段在主数据 class 构造函数中已标记为 val
,这怎么可能?
反射在这里起作用吗?
在 Kotlin 中 val
不是 真正的 final 吗?
Firebase 确实使用反射 set/get 值。具体来说,它使用 JavaBean 模式来识别属性,然后 gets/sets 使用它们的 public
getter/setter 或使用 public
字段。
您的 data class
被编译成与此 Java 代码等效的代码:
public static final class Record {
@NotNull
private final String firstName;
@NotNull
private final String lastName;
@NotNull
private final String city;
@NotNull
private final String country;
@NotNull
private final String email;
@NotNull
public final String getFirstName() { return this.firstName; }
@NotNull
public final String getLastName() { return this.lastName; }
@NotNull
public final String getCity() { return this.city; }
@NotNull
public final String getCountry() { return this.country; }
@NotNull
public final String getEmail() { return this.email; }
public Record(@NotNull String firstName, @NotNull String lastName, @NotNull String city, @NotNull String country, @NotNull String email) {
Intrinsics.checkParameterIsNotNull(firstName, "firstName");
Intrinsics.checkParameterIsNotNull(lastName, "lastName");
Intrinsics.checkParameterIsNotNull(city, "city");
Intrinsics.checkParameterIsNotNull(country, "country");
Intrinsics.checkParameterIsNotNull(email, "email");
super();
this.firstName = firstName;
this.lastName = lastName;
this.city = city;
this.country = country;
this.email = email;
}
...
}
在这种情况下,当我需要将它们写入数据库时,Firebase 使用 public getter 获取 属性 值,并在需要设置 [=27= 时使用字段] 从数据库中读取值时的值。
我一直在开发 Kotlin 后端服务,偶然发现了 Firestore documentSnapshot.toObject(className::class.java)
方法。
采用以下 Kotlin data class
:
data class Record(
val firstName: String = "",
val lastName: String = "",
val city: String = "",
val country: String = "",
val email: String = "")
以及我的 Repository
class 中的以下代码:
if (documentSnapshot.exists()) {
return documentSnapshot.toObject(Record::class.java)!!
}
现在,据我了解,方法 documentSnapshot.toObject(className::class.java)
需要并调用无参数默认构造函数,例如val record = Record()
。
此调用将调用主构造函数并将其中声明的默认值(在数据 class Record
、空字符串 ""
的情况下)分配给字段.
然后,它使用 public setter 方法将实例的字段设置为在 document
.
假设字段在主数据 class 构造函数中已标记为 val
,这怎么可能?
反射在这里起作用吗?
在 Kotlin 中 val
不是 真正的 final 吗?
Firebase 确实使用反射 set/get 值。具体来说,它使用 JavaBean 模式来识别属性,然后 gets/sets 使用它们的 public
getter/setter 或使用 public
字段。
您的 data class
被编译成与此 Java 代码等效的代码:
public static final class Record {
@NotNull
private final String firstName;
@NotNull
private final String lastName;
@NotNull
private final String city;
@NotNull
private final String country;
@NotNull
private final String email;
@NotNull
public final String getFirstName() { return this.firstName; }
@NotNull
public final String getLastName() { return this.lastName; }
@NotNull
public final String getCity() { return this.city; }
@NotNull
public final String getCountry() { return this.country; }
@NotNull
public final String getEmail() { return this.email; }
public Record(@NotNull String firstName, @NotNull String lastName, @NotNull String city, @NotNull String country, @NotNull String email) {
Intrinsics.checkParameterIsNotNull(firstName, "firstName");
Intrinsics.checkParameterIsNotNull(lastName, "lastName");
Intrinsics.checkParameterIsNotNull(city, "city");
Intrinsics.checkParameterIsNotNull(country, "country");
Intrinsics.checkParameterIsNotNull(email, "email");
super();
this.firstName = firstName;
this.lastName = lastName;
this.city = city;
this.country = country;
this.email = email;
}
...
}
在这种情况下,当我需要将它们写入数据库时,Firebase 使用 public getter 获取 属性 值,并在需要设置 [=27= 时使用字段] 从数据库中读取值时的值。