Java String类
来源:互联网 发布:mac 安装oracle 编辑:程序博客网 时间:2024/06/02 03:05
String的不可变性
Java.lang包下面的的String在平时很常见,我们都知道String是不可变类。简单说来,不可变类的实例是不能被修改的,每个实例中包含的信息都必须在该实例创建的时候就提供出来,并且在对象的整个生存周期内固定不变。
在String类中,是通过一个不可变的字符数组来存储对象的字符序列的,final关键字使这个变量是不可变的,所以Sting对象的内容也是不可变的。
private final char value[];
很多初学者对于不可变类还是很不能理解,因为通过下面的代码,看起来改变了字符串对象s。
public static void main(String[] args) { String s = "abc"; System.out.println(s); s = "cde"; System.out.println(s); }
输出结果为
abccde
其实这是因为对String对象的创建和存储机制不了解产生的误解。下面我们来探讨String的对象创建和初始化。
String的对象创建和初始化机制
字符串的声明和初始化主要有以下两种情况:
(1) 对于String s1=new String(“abc”)语句与String s2=new String(“abc”)语句,存在两个引用对象s1、s2,两个内容相同的字符串对象”abc”,它们在内存中的地址是不同的。只要用到new总会生成新的对象。
(2) 对于String s1 = “abc”语句与String s2 = “abc”语句,在JVM中存在着一个字符串池string pool,其中保存着很多String对象,并且可以被共享使用,s1、s2引用的是同一个常量池中的对象。当创建一个字符串常量的时候,例如String s = “abc”,会首先在字符串常量池中查找是否已经有相同的字符串被定义,它的判断依据是String类equals(Object obj)方法的返回值,也就是判断是否有相同的字符串序列。如果已经定义,则直接获取对其的引用,此时不需要创建新的对象,如果没有定义,则首先创建这个对象,然后把它加入到字符串池中,再将它的引用返回。
例如:
String s1=“abc”; //在常量区里面存放了一个”abc”字符串对象String s2=“abc”; //s2引用常量区中的对象,因此不会创建新的对象String s3=new String(“abc”) //在堆中创建新的对象String s4=new String(“abc”) //在堆中又创建一个新的对象
回到String对象的不可变特性
public static void main(String[] args) { String s = "abc"; //在常量区中存放一个"abc"字符串对象,并把s指向这个对象 System.out.println(s); s = "cde"; //在string pool中查找是否存在"dec",不存在则创建这个对象,并把s指向这个对象 System.out.println(s); }
通过上面的分析,我们可以知道,改变的只是s的指向,而“abc”和“cde”这两个字符串对象并没有改变,内存中字符串对象如下所示:
执行String s = “abc”后s的指向
执行 s = “cde”后s的指向
改变的只是s的指向,而字符串对象的内容并没有发生改变。
另外,在进行字符串的对象创建时我们还可能会使用“+”来进行字符串的连接, 如果用+号来实现String的串接时有两种情况:
1)仅当+号两边均为字符串常量时,才将其+后的结果当做字符串常量,且该结果直接放入String Pool;
2)若+号两边有一方为变量时,+后的结果即当做非字符串常量处理(等同于new String()的效果)。
改变不可变的String对象
如果我们真的需要去改变String对象,那么应该怎么做呢?
这个时候就需要用到java的反射机制了,我们可以通过反射机制去获取String对象的value数组,并修改value字符数组的相应内容,这样子字符串对象也会相应的发生改变。代码如下:
public static void main(String[] args) { try { String s = "abc"; Field valuefield = String.class.getDeclaredField("value"); valuefield.setAccessible(true); char[] value = (char[]) valuefield.get(s); value[1] = '_'; System.out.println(s); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出结果如下:
a_c
- 【java】:java String类
- 学习java String类
- java手记---String类
- java string类详解
- JAVA String类学习
- java String 类源代码
- Java.String类
- JAVA的String 类
- java String 类细节
- Java String类总结
- java-String类
- java基础---->String类
- java String类
- JAVA的String 类
- JAVA String类详解
- JAVA string 类
- Java API String类
- java String 类详解
- mybatis @param的解释
- Spark 优化
- 关于input[type=file]表单控件的相关知识点
- UVA 12558 埃及分数(迭代搜索)
- 112家it公司薪水
- Java String类
- CentOS 7 安装Java JDK
- algorithm 题集六 (16.11.12)
- UGUI 打字机效果
- [网络安全]dSploit-Android系统下的网络分析和渗透套件的使用
- poj 2251 Dungeon Master (BFS)
- linux内核sysfs详解-1
- 【聚类】性能度量
- 【NOIP模拟题】【DFS】【位运算】【舞蹈链】2016.11.12第三题题解