私が実装しようとしている確認 Stack<E>
に基づいてJava配列 Kotlinインチ しかし、私は使用して問題を抱えているKClassを私のジェネリックパラメータの型と<E>
ヌル値を許可します。
Javaの一般的なタイプは、実行時には使用できませんが、配列の種類があります。私はそこにビルトインされるように型チェックの実行時にこの機能を使用したいです。
確認/未チェックの詳細については、ここで見つけることができますhttps://stackoverflow.com/a/530289/10713249
interface Stack<E> {
fun push(elem: E)
fun pop(): E
}
class CheckedStack<E>(elementType: Class<E>, size: Int) : Stack<E> {
companion object {
inline fun <reified E> create(size: Int): CheckedStack<E> {
//**compile error here**
return CheckedStack(E::class.javaObjectType, size)
}
}
@Suppress("UNCHECKED_CAST")
private val array: Array<E?> = java.lang.reflect.Array.newInstance(elementType, size) as Array<E?>
private var index: Int = -1
override fun push(elem: E) {
check(index < array.size - 1)
array[++index] = elem
}
override fun pop(): E {
check(index >= 0);
@Suppress("UNCHECKED_CAST")
return array[index--] as E
}
}
私は、このコードは次のように動作することを期待します。
fun main() {
val intStack = CheckedStack.create<Int>(12) // Stack must store only Integer.class values
intStack.push(1); //[1]
intStack.push(2); //[1, 2]
val stackOfAny: Stack<Any?> = intStack as Stack<Any?>;
stackOfAny.push("str") // There should be a runtime error
}
しかし、私は、コンパイルエラーが発生しています
Error:(39, 42) Kotlin: Type parameter bound for T in val <T : Any> KClass<T>.javaObjectType: Class<T>
is not satisfied: inferred type E is not a subtype of Any
それを修正するために、私は型パラメータをバインドする必要があります<E : Any>
が、私は、スタックがNULL可能値で作業できるようにする必要があります<T : Any?>
。どのようにそれを修正するには?
なぜKClassはとして宣言されてKClass<T : Any>
いませんかKClass<T : Any?>
?
UPD:それは使用している場合は動作しますE::class.java
代わりにE::class.javaObjectType
プロパティがあるのでval <T> KClass<T>.java: Class<T>
typeのparam持つ<T>
注釈付きを@Suppress("UPPER_BOUND_VIOLATED")
。
しかし、プロパティにはval <T : Any> KClass<T>.javaObjectType: Class<T>
タイプがあります<T : Any>
。
私の場合は、Kotlinは(私の場合)Integer.classにではなく、int型のIntをコンパイルします。しかし、私は、それはいつものようにうまくいくことはよく分かりません。
彼らはクラスオブジェクトを持っていないので、NULL可能なタイプは、自分自身のクラスではありません。だからこそKClass
の型パラメータを持つAny
上限。
あなたは呼び出すことができます::class.java
NULL可能物象化タイプに、それは、対応するnull以外のタイプで同じコールと同じクラスのオブジェクトに評価されます。あなたが交換するのであればE::class.javaObjectType
とE::class.java
、要素の型は、実行時にチェックされますが、ヌルのチェックは行われません。
あなたがnullチェックが必要な場合は、自分でそれらを追加することができます。私はまた、ファクトリメソッドに配列作成を動かす示唆しています。ここではあなたがそれを行うことができる方法です。
class CheckedStack<E>(private val array: Array<E?>, private val isNullable: Boolean) : Stack<E> {
companion object {
// This method invocation looks like constructor invocation
inline operator fun <reified E> invoke(size: Int): CheckedStack<E> {
return CheckedStack(arrayOfNulls(size), null is E)
}
}
private var index: Int = -1
override fun push(elem: E) {
if (!isNullable) elem!!
check(index < array.size - 1)
array[++index] = elem
}
override fun pop(): E {
check(index >= 0)
@Suppress("UNCHECKED_CAST")
return array[index--] as E
}
}