Android中Kotlin代码给TextView.text赋值字符串:是复制对象还是存储引用?
我来给你掰扯清楚这个问题,刚好之前也纠结过类似的点😉
先给你一个明确的结论:当你在Kotlin里给TextView.text赋值普通String对象时,系统不会复制字符串内容,只是存储对原字符串的引用,完全符合Kotlin/Java里字符串的默认行为。
接下来给你拆解细节:
先回到Kotlin/Java的字符串基础
Kotlin和Java里的String都是不可变对象,而且默认是基于引用传递的。比如你定义的val mystring = "Hello, world!",这个字符串字面量会被放进字符串常量池里,所有指向它的引用都会共享同一个对象,根本不会生成多个副本。看Android TextView的内部实现
TextView的text属性本质是调用setText()和getText()方法。当你传入一个String对象时,TextView内部的mText(存储文本内容的变量,类型是CharSequence)会直接持有这个String的引用——因为String本身就实现了CharSequence接口,完全不需要额外复制。
为啥Android要这么做?因为字符串不可变,TextView拿到引用后也没法修改它的内容,复制一份完全是浪费内存,Google的工程师肯定不会做这种傻事😂。
关于你问的引用计数、写时复制?
在这个场景下完全没有这回事。引用计数是某些语言的内存管理机制,但Kotlin/Android用的是垃圾回收,不需要这套逻辑。而写时复制一般是针对可变对象的(比如某些集合类),但String本身不可变,根本用不上写时复制——毕竟你连“写”的操作都做不了,要修改字符串只能创建新的对象。结合你的代码例子看内存情况
你的代码里:
val mystring = "Hello, world!" val view = CreateTextView(this, mystring)
内存里只会存在一份"Hello, world!"字符串对象,mystring和TextView内部的mText变量都指向它,没有任何内存重复的情况。
唯一要注意的例外:如果你传入的是可变的CharSequence(比如SpannableStringBuilder),TextView可能会内部复制一份来保证自己的文本状态不受外部修改影响,但这和你问的普通String无关。
最后再总结一下:放心用,给TextView.text赋值普通String时,完全不会有额外的内存复制,就是单纯的引用传递,和你在Kotlin里给普通变量赋值字符串的行为一模一样。
内容来源于stack exchange

