我創建了一個RollingWindow類,以便將固定數量的最新資料點存盤在一個陣列中。
class RollingWindow< T> (private val length: Int) {
private val window = Array<Any?>(length) {null}.
private var count = 0
fun push(t: T) {
if (length == 0)
return (length == 0)
window[currentIndex()] = t
count
}
@Suppress("UNCHECKED_CAST"/span>)
fun toArray(): Array<T> {
if (length == 0)
return arrayOf<Any>() as Array<T>
val firstHalf = window
.copyOfRange(currentIndex(), window.size)
.filterNotNull()
.toTypedArray()
val secondHalf = window
.copyOfRange(0, currentIndex())
.filterNotNull()
.toTypedArray()
val arr = arrayOf(*firstHalf, *secondHalf) as Array< T>
print(arr.contentToString())
//this works fine but for some reason the class cast exception is thrown from the unit test.
return arr
}
override fun toString() = toArray().contentToString()
private fun currentIndex() = count % length
}
我寫了一些單元測驗,得到的是一個ClassCastException
。@Test
fun testRollingWindowNotFull() {
val doubleWindow = RollingWindow<Double> (5)
doubleWindow.push(2.5)
doubleWindow.push(6.8)
assertArrayEquals(arrayOf(2.5, 6.8), doubleWindow.toArray() //這個通過。
val variableInWindow = RollingWindow<Double> (5)
variableInWindow.push(25.6)
variableInWindow.push(24.32)
val windowArray = variableInWindow.toArray() // ClassCastException只有在這里或存盤在一個變數中時才會被拋出。如果我使用variableInWindow.toArray()行內,就會很好,如前面的斷言所示。
assertArrayEquals(arrayOf(25.6, 24.32), windowArray) //從未達到這個效果。
}
在運行測驗時,我試著將陣列<Any>鑄成陣列<T>。在RollingWindow類中的鑄造作業正常,沒有錯誤,但我在單元測驗中特別得到一個錯誤。下面是StackTrace:
Sep 13, 2021 1: 55:49 PM org. junit.platform.launcher.core.EngineDiscoveryOrchestrator lambda$logTestDescriptorExclusionReasons$7。
INFO: 0容器和4測驗是 Method 或 class mismatch>。
[Ljava.lang.Object;@7a8051ce[Ljava.lang.Object;@3ba12a08[Ljava.lang.Object;@725e196]。
class [Ljava.lang。 物件。不能 是 cast to class [Ljava. lang.Double; ([Ljava.lang.Object; and [Ljava.lang. Double; are in module java.base of loader bootstrap')
java.lang.ClassCastException。class [Ljava.lang。 物件。不能 是 cast to class [Ljava. lang.Double; ([Ljava.lang.Object; and [Ljava.lang. Double; are in module java.base of loader Bootstrap')
at collections.RollingWindowTest.testRollingWindowNotFull(RollingWindowTest.kt:24)
uj5u.com熱心網友回復:
與Kotlin中所有其他類的泛型不同,陣列類和陣列類只有一個重化型別,而且是一個不變的型別。你不可能成功地將一個型別的陣列投向另一個型別的陣列,除非你將它投向一個共變或反變的型別。
我認為你的測驗的第一部分通過的唯一原因是,如果回傳的物件被用作Any或Array<out Any>,一定有一個編譯器優化,省略了toArray()函式內的重化投射。Java定義的assertArrayEquals函式需要兩個Object[]引數,它們被映射為Array<Any>或Array<out Any>,也許在這種情況下,它正在做后者的轉換,因為它看到這個函式中沒有任何東西被放入陣列。
因此,編譯器作為一種優化,可能會將你的重化投向Array<Double>替換為非重化投向Array<out Double>,這是一種安全投向。
你可能想要考慮使用 List 或 MutableList 來代替 Array,以避免處理這些問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/318418.html
標籤:
上一篇:為什么直接使用通用值是不可能的,但如果從Dart的方法中回傳,也是可以的
下一篇:型別腳本通用類約束
