使用 Any 作為集合型別比使用具體型別消耗更少的記憶體嗎?
認為
val list1 = listOf<Any>("ABC", "DEF", "GHI", "JKL", "MNO")
val list2 = listOf<String>("ABC", "DEF", "GHI", "JKL", "MNO")
我想知道list1消耗的記憶體是否比list2因為String型別分配記憶體來存盤其屬性(例如size)
那么,list1如果我不使用任何String型別函式,使用它會更好嗎?
編輯
如果我想在集合中使用其他型別怎么辦?
list = listOf<Any>("ABC", 123, 12.34)
是不是比
list = listOf<String>("ABC", "123", "12.34")
編輯 2
感謝 @Jo?o Dias 和 @gidds
正如@gidds 所說:
該串列不直接包含 String 物件或 Any 物件——它包含參考。
并且 String 參考的大小與 Any 參考或任何其他型別的參考完全相同。?
所以,List<String>和List<Any>是完全一樣的,因為的型別擦除-它通過@若奧·迪亞斯指出-與編譯時和運行時型別的不同
但是,這是否意味著
val list1 = listOf<Any>("ABC", "DEF", "GHI")
和
val list2 = listOf<String>("ABC", "DEF", "GHI")
消耗相同的記憶體
val list3 = listOf<List<List<List<String>>>>(
listOf(listOf(ListOf("ABC"))),
listOf(listOf(ListOf("DEF"))),
listOf(listOf(ListOf("GHI")))
)
AFAIK,String基本上是Char. AString包含對 的參考Char。并且因為在 Kotlin 中一切都是物件,那么Char里面的每個都String應該包含對堆中值的參考,我在這里正確嗎?
如果是這樣的話,List<String>消耗更多的記憶體而不是List<Any>因為List<String>有超過 1 個參考,這是否有意義。
uj5u.com熱心網友回復:
到目前為止沒有解決的一點是串列不直接包含String物件或Any物件——它包含參考。
并且String參考與Any參考或任何其他型別的參考的大小完全相同。(該大小取決于運行代碼的 JVM 的內部結構;它可能是 4 或 8 個位元組。請參閱這些 問題。)
當然,被參考的物件也會在堆中占據自己的空間;但在這兩種情況下都是一樣的。
編輯添加:
如何實施List和String實施的內部細節與原始問題無關。(這很好,因為它們因實作而異。)JVM 語言(例如 Kotlin)只有兩種值:原語(Int, Short, Long, Byte, Char, Double, Float, Boolean)和參考(物件或陣列)。
因此,任何集合,如果它不是基元的集合,則是參考的集合。這適用于所有List實作。所以,你list1和list2物件將是完全一樣的大小,只對他們持有(或可容納)參考的數量根據,而不是什么是在那些參考。
如果你想要更深入的圖片,list1是一個參考,指向一個實作List介面的物件。有許多不同的實作,我不知道 Kotlin 會選擇哪一個(同樣,這可能會因版本而異),但例如它是一個ArrayList. 它至少有兩個屬性:一個大小(可能是一個Int),以及一個對陣列的參考,該陣列包含對串列中專案的參考。(陣列通常會大于串列的當前大小,因此您可以添加更多專案而不必每次都重新分配陣列;陣列的當前大小稱為串列容量。)如果那些專案是Strings,那么確切的內部表示取決于 JVM 版本,但它可能是一個至少具有三個屬性的物件:一個 的陣列Char,一個Int給出陣列中字串的起始索引,另一個Int給出長度。
但正如我所說,細節會隨著時間和 JVM 版本而變化。不變的是List參考的集合,參考的大小不依賴于它的型別。因此,String參考串列(所有其他條件相同)將占用與Any對這些相同字串的參考串列完全相同的空間。
(而且,正如在別處提到的,由于運行時的型別擦除,JVM 沒有型別引數的概念,因此物件實際上是相同的。)
當然,“深度大小”(串列占用的總堆空間及其包含的物件)將取決于這些物件的大小——但在我們討論的情況下,這些是完全相同的String物件,所以那里的大小也沒有區別。
uj5u.com熱心網友回復:
它對記憶體消耗沒有任何影響。您正在構建具有完全相同內容的完全相同的串列。此外,還有一種叫做型別擦除的東西,它是這樣的:
型別擦除可以解釋為在編譯時強制執行型別約束并在運行時丟棄元素型別資訊的程序。
這意味著在運行時,如果您在記憶體消耗方面使用第一個或第二個,則沒有任何區別List<String>或List<Any>只是List沒有任何區別。關于代碼可讀性、可維護性和健壯性,您絕對應該使用List<String>. 鑒于在 Kotlin 中List默認公開的串列是只讀的(感謝 @Alex.T 和 @Tenfour04 的提示,如果串列中的元素也是不可變的,并且 的具體實作List確實是不可變的,則只能將其視為不可變的,例如,考慮一個list : List<String>具有底層可變屬性的屬性,ArrayList<String>那么list它仍然不是完全不可變的,因為因為強制轉換允許您從中添加或洗掉元素(list as ArrayList<String>).add("new-element")) 你基本上只有使用的缺點List<Any>(因為如果你想迭代或使用它的任何元素,你當時就會知道它是Any一個位元定型別更難使用的元素,如String)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/373410.html
上一篇:誰能解釋一下這是如何作業的?
