私はいくつかのプライベートプロパティが必要なテストケースを書いています。これらのプライベートデータはプライベートメソッドから生成されるため、計算が完了した後にリフレクションを使用することにしました。後で私は代理プロパティを思い出して、一般的な代議員を書くことにしました。ここで私は今のところ得たコードは次のとおりです。イニシャライザでこのヌルチェックを安全に解決するにはどうすればよいですか?
fun <T> reflect(instance: Any, initOnce: Boolean = true) = ReflectBackedProperty<T>(initOnce, instance)
class ReflectBackedProperty<T>(val initOnce: Boolean, val instance: Any): ReadOnlyProperty<Any, T> {
var initialized = false
lateinit var cache: T // <--- (a)
override opertaor fun getValue(thisRef: Any, property: KProperty<*>): Any? {
@Suppress("UNCHECKED_CAST")
if (!initialized || !initOnce) {
cache = instance.javaClass.getDeclaredField(property.name).get(instance) as T
initialized = true
}
return cache
}
}
あなたが見ることができるように、プロパティcache
がinitOnce
が設定されている場合は、getValue
の呼び出しによって初期化され、後続の呼び出しではなく、高価な反射を呼び出す維持のキャッシュを使用します。
非常に不幸なことは、Tがnull可能な型であり、late initのメカニズムが壊れている可能性がありますが、私がnull
で初期化してもTが非nullタイプとnull安全性が壊れています。
現在のところ、nullを返すJava関数の戻り値を使用して初期化することで、この問題を解決しました。私は生成されたバイトコードを検査し、kotlinコンパイラがnullチェックをしていないことを確認しましたが、現在は動作しますが、将来のkotlinバージョンではこのようなチェックが行われ、このトリックが破損することに心配しています。どのように私はこれを克服するはずですか?
私はこれを使用しています。以下のコードはパブリックドメインに公開されています。あなたが好きな場合はこのページを言及するか、何もしないでください。
KTHacks.java
public final class KTHacks {
private KTHacks() {
throw new UnsupportedOperationException();
}
/**
* Forge a null into a platform type and take advantage of relaxed null-checks.
* @param <T>
* @return
*/
public static <T> T NULL() {
return null;
}
}
ReflectBackedProperty.kt
import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty
fun <T> reflect(instance: Any, initOnce: Boolean = true) = ReflectBackedProperty<T>(initOnce, instance)
class ReflectBackedProperty<T>(val initOnce: Boolean, val instance: Any): ReadOnlyProperty<Any, T> {
var initialized = false
var cache: T = KTHacks.NULL()
override operator fun getValue(thisRef: Any, property: KProperty<*>): T {
@Suppress("UNCHECKED_CAST")
if (!initialized || !initOnce) {
cache = instance.javaClass.getDeclaredField(property.name).get(instance) as T
initialized = true
}
return cache
}
}
これまでのところ、これが最良の解決策です。もしnullとnullでない型の両方を望むなら、普通のJavaをハックしたり使う必要があります。 – glee8e
@ glee8e Javaでできるコードがありません。コトリンではできません – voddan
私の更新 – voddan