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的指向

执行String s = "abc"后s的指向

执行 s = “cde”后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
1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 oppo音量键坏了怎么办 魅蓝手机屏幕碎了怎么办 手机钢化膜边缘有气泡怎么办 手机贴钢化膜边缘有气泡怎么办 苹果手机钢化膜边缘有气泡怎么办 手机膜里的水泡怎么办 膜贴好了有气泡怎么办 后档玻璃膜气泡怎么办 贴膜里面有灰尘怎么办 贴膜边缘不粘怎么办 贴膜时候的气泡怎么办 贴手机膜起泡了怎么办 手机膜起泡泡了怎么办 手机膜鼓起来了怎么办 贴膜中间有气泡怎么办 新车贴膜有气泡怎么办 贴手机膜进灰尘怎么办 贴手机膜有灰尘怎么办 华为mate10后机壳碎了怎么办 手机屏和壳分开了怎么办 oppoa33手机开不了机怎么办 7p背面刮花了怎么办 oppo手机左右两键失灵怎么办 苹果5s屏幕翘起怎么办 0pp0手机有点卡怎么办 手机用久有点卡怎么办 手机有点卡怎么办魅蓝 苹果6排线接反了怎么办 oppo手机解锁密码忘了怎么办 魅蓝5音量小怎么办 魅蓝5密码忘记了怎么办 魅蓝note3锁定了怎么办 魅族mx5系统铃声没有了怎么办 魅族主板坏了怎么办 魅族mx5螺丝滑丝怎么办 魅族魅蓝e手机被锁了怎么办 魅蓝e被锁机了怎么办 魅蓝3s卡顿怎么办 魅族note5玩王者荣耀卡怎么办 魅族手机内存不够怎么办 魅族手机音量小怎么办