String不可变不可被继承源码分析
来源:互联网 发布:阿里云域名解析到主机 编辑:程序博客网 时间:2024/06/07 18:54
是否可变,String类能否被继承
- 重点,String是不可变的!String类不能被继承!
- String类是不可变的。一个String实例,创建完成后就无法改变。
- 能改变的只是String的引用,状态,对象内的成员变量都无法改变,无论是基本数据类型还是引用数据类型。
区分对象和对象引用
//一个字符串,s1这个是一个存放物理地址的引用对象,s1———》指向 "hello"String s1 = "hello";System.out.println(s1);//这里实际情况是新创建了一个字符串“world”, s1————》指向改变"world"s1 = "world"System.out.println(s1);结果: helloworld
- 进一步说明时候String不可变
String s1 = "hello";System.out.println(s1);//将字符e替换成a,实现是替换之后,创建了一个新的String对象,并不影响s1s1.repalce('e','a');System.out.println(s1);结果:hellohello
- 补充说明一点,引用数据类型的引用,根据底层实现,其实是一个引用–>另一个引用–>堆区内存中保存的‘对象’
String类的final
- String 类在 JDK 7 源码
//可以看出 String 是 final 类型的,表示该类不能被其他类继承。//String 字符串是常量,其值在实例创建后就不能被修改,但字符串缓冲区支持字符串的引用的改变public final class String implements java.io.Serializable, Comparable<String>, CharSequence{...}
- String的成员变量
- 这是一个字符数组,并且是 final 类型,用于存储字符串内容。 fianl 关键字修饰,一旦被创建,其值无法改变。
String 其实是基于字符数组 char[] 实现的。
/**The value isused for character storage.*/private final char value[];
看上去像改变String的方法其实无法改变String
- String的replace(char oldChar, char newChar)方法。
public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } //这行代码是关键,返回的是一个新的String。 return new String(buf, true); } } return this; }
- 其他方法的内部都是重新创建新的String对象,并且返回这个新的对象,原来的对象无法改变。这也是replace, substring,toLowerCase等方法都存在返回值的原因。
String对象真的不可变吗?
- 现在我知道String的成员变量是private final ,无法改变。那么在这几个成员中, value比较特殊,因为是一个引用变量,而不是真正的对象。value是final修饰的,也就是说final不能再指向其他数组对象,那么我能改变value指向的数组吗? 比如将数组中的某个位置上的字符变为下划线“_”。 至少在我们自己写的普通代码中不能够做到,因为我们根本不能够访问到这个value引用,更不能通过这个引用去修改数组。
那么用什么方式可以访问私有成员呢? 没错,用反射, 可以反射出String对象中的value属性, 进而改变通过获得的value引用改变数组的结构。下面是实例代码:
public static void testReflection() throws Exception { //创建字符串"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 Worlds = Hello_World
- 在这个过程中,s始终引用的同一个String对象,但是再反射前后,这个String对象发生了变化, 正常使用String的时候,是不可能会去用到映射的,所以,这只是知识体系中的知识点,并不是编程代码的应用。这个反射的实例还可以说明一个问题:如果一个对象,他组合的其他对象的状态是可以改变的,那么这个对象很可能不是不可变对象。例如一个Car对象,它组合了一个Wheel对象,虽然这个Wheel对象声明成了private final 的,但是这个Wheel对象内部的状态可以改变, 那么就不能很好的保证Car对象不可变。
阅读全文
1 0
- String不可变不可被继承源码分析
- String为什么不可变,String源码解析
- 不可变的String
- Java String不可变
- String对象不可变
- String为什么不可变
- string 不可变类
- String对象不可变
- String的不可变
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Java中的String为什么是不可变的? -- String源码分析
- Types of Properties--Accessor Properties
- Jdk8新特性
- Selenium环境配置
- Java的垃圾回收机制,GC,和变量的创建和删除的关系(即变量的作用域,for循环中的某个变量,出了for循环再引用就会报错了,因为该变量已经被从内存中删掉了)
- PCA详细讲解
- String不可变不可被继承源码分析
- Kafka消息序列化和反序列化(下)
- JQ对用户名异步校验(JQ的AJAX)
- 有关java项目
- activiti项目使用总结
- jmeter 集成jenkins 邮件正文报告乱码解决
- QT 信号与槽有连接 槽未响应
- (2012蓝桥杯) 奇怪的比赛 某电视台举办了低碳生活大奖赛。题目的计分规则相当奇怪: 每位选手需要回答10个问题(其编号为1到10),越后面越有难度。
- 分布式系统核心问题