如何理解在数据类型中元素不能修改?
我所理解的元素修改是:
不能对已经赋值或者初始化的数据类型进行元素的修改,这里的修改不是指片面意思上的输错了数值,将光标移到对应位置,按下删除键,再进行数据的修改等操作,也不是指对对象的重新赋值。
重新赋值:初始化完成后又进行重新赋值
修改:创建后对象后对某些元素进行添加、删除等操作
- 例如Python中字符串不能被改变,word=[‘abcdefgh’],如果运行word[0] = 'm’会导致错误==‘str’ object does not support item assignment.==
关于字符串原码详细的信息,可以查看https://zhuanlan.zhihu.com/p/120980114
变长可变对象 - 例如 List,创建后还能添加、删除元素
变长不可变对象 - 例如 String,Tuple, 创建后,不再支持添加、删除等操作
word = 'abcdefgh'
word[0] = 'm'
print(word)
- List(列表)可以完成大多数集合类的数据结构实现,元素类型可以不相同,列表的元素可以修改。。
a = [0,1,2,3,4,5,6,7,8,9]
a[2:5] = [11,11,11]
print(a)
- Tuple(元组)与列表类似,但是元组的元素不能修改。
tuple = ('abc',123,3.14,'kim')
tuple[0] = 'love'print(tuple)
在Java语言中,菜鸟教程中解析了String类不可改变的实例。简单来说:String类利用了final修饰的char类型数组存储字符。字符串的本质是字符数组,value属性用来存放字符串中的字符,final属性修饰,是不可被修改的。
以下内容来源https://www.cnblogs.com/Java-JJ/p/12625888.html
String不可变但不代表引用不可以变
String str = “Hello”;
str = str + " World";
System.out.println(“str=” + str);
结果:
str=Hello World
解析:
实际上,原来String的内容是不变的,只是str由原来指向"Hello"的内存地址转为指向"Hello World"的内存地址而已,也就是说多开辟了一块内存区域给"Hello World"字符串。
通过反射是可以修改所谓的“不可变”对象
// 创建字符串"Hello World", 并赋给引用s
String s = “Hello World”;
System.out.println("s = " + s); // Hello World
// 获取String类中的value字段
Field valueFieldOfString = String.class.getDeclaredField(“value”);
// 改变value属性的访问权限
valueFieldOfString.setAccessible(true);
// 获取s对象上的value属性的值
char[] value = (char[]) valueFieldOfString.get(s);
// 改变value所引用的数组中的第5个字符
value[5] = ‘_’;
System.out.println("s = " + s); // Hello_World
结果:
s = Hello World
s = Hello_World
解析:
用反射可以访问私有成员, 然后反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。但是一般我们不会这么做,这里只是简单提一下有这个东西。
是否可以继承 String 类
String 类是 final 类,不可以被继承。
重新赋值的“背后”
- 对于String类对象重新赋值
执行代码:
public class Text01 {public static void main(String[] args) {String s = "Google";System.out.println("s = " + s);s = "Runobb";System.out.println("s = " + s);}
}
得到的结果:
s = Google
s = Runobb
两次输出字符串string的结果看似是改变了,但是第一次赋值的“Google”还存放在内存中。
原因在于实例中的 s 只是一个 String 对象的引用,并不是对象本身,当执行 s = “Runoob”; 创建了一个新的对象 “Runoob”,而原来的 “Google” 还存在于内存中。
Java虚拟机中,栈(stack)中分配的是基本数据类型和自定义对象的引用。堆(heap)中分配的是对象,创建new的对象。方法区中存放的是类的信息、static变量、常量。当执行 s = "Runoob"时,对象 s 指向栈中新的引用“Runoob”。所以s的结果看似改变,实则是和栈中另外的值手牵手了,而旧相好"Google"还在栈中原来的地方静静等待着。所以说String对象是不可变的,"Google"还在原来的地方,没有任何改变。
以上是自己在学习过程中对于数据类型的元素是否可以被修改的理解,如果哪里有错误,还请提醒一下。