首页 >> 快讯 >

string类型和char类型的区别(string类型)

2023-08-20 06:32:56 来源: 用户: 

你们好,最近小时发现有诸多的小伙伴们对于string类型和char类型的区别,string类型这个问题都颇为感兴趣的,今天小活为大家梳理了下,一起往下看看吧。

1、 从何说起,我们先看看源代码,看看源代码对String类的解释:

2、 在java程序中,所有单词,比如“ABC”,都是String类的实例。

3、 字符串是常量,它们的值(注意是值)在创建后是不能更改的。

4、 Stringbuffer支持可变字符串。因为字符串类对象是不可变的,所以它们可以被共享。例如,String STR="ABC "和String STR=New String ("STR ")的值相等。

5、 Java语言提供了对字符串操作的特殊支持,它使用了StringBuilder类的append实现(下面将分析更详细的解释)。使用toString实现字符串转换。

6、 String类的修饰符是final,这意味着这个类不能被继承。重点是数据结构:字符数组。

7、 String类中有一个字符数组:private final char value[];可以看出,java字符串是以字符数组的形式实现的,并且是final,也就是说值是常量,它的值在确定之后是不可变的。

8、 同样如此,类似于StringBuilder中的append方法在String类中找不到。为了看得更清楚,

9、 看一下StringBuilder的值数组(在继承的抽象类AbstractStringBuilder中定义),char[]value;这是一个可变字符数组,没有最后的修饰。

10、 所以可以使用append方法追加一个字符串。

11、 接下来,看看它的equals方法,比较字符串是否相等。算法的核心也比较简单,就是从第一个位置开始比较,不一样就返回false,否则就比较下一个位置。

12、 HashCode也被重写了。如果两个字符串相等,则其hashCode的返回值是相同的。计算公式为:

13、 s[0]*31^(n-1) + s[1]*31^(n-2) + . + s[n-1]

14、 s是字符数组,n是它的长度。

15、 看完equals,我们再来看一个小程序,先写一个测试类。

16、 查看输出。首先要明确,equals是调用String类的方法,比较值数组的每一位是否相同,也就是比较变量引用对象的值。而“==”就是比较变量的引用是否相同。

17、 所以第一和第二的输出并不意外,这一点上面已经分析过了。

18、 关键是看第三和第四个输出:

19、 因为==比较的是引用的值而不是引用的值,所以意味着s1和s3指向同一个引用,而s2指向另一个引用。

20、 有两点需要强调:

21、 第一点,s1和s2的引用都是String对象,为什么这么说,因为可以通过反射拿到其所属的类java.lang.String。下图1

22、 第二点,也是比较关键的一点;到底创建了几个对象?如有异议欢迎指正。

23、 首先来看一眼jvm对String的管理:

24、 首先堆用于存储String类的实例;

25、 其次每一个jvm会维护一张内部表StringTable,用于存储程序运行时出现过的不重复的String对象的引用(不重复的判断方式equals)。

26、 常量池:存储字符串对象的引用。

27、 (1)String s1=“abc”,在StringTable中查找此字符串(使用hashCode和equals),如果有取其引用赋值给常量池;否则,创建一个字符串对象,

28、 并将其引用保存在常量池和StringTable中。在此例子中会在堆中创建一个对象A,然后将其引用存储到StringTable和常量池入口中。

29、 (1)String s2=new String(”abc“),new String每次都会在堆中创建一个新的对象B。检查StringTable中是否存在此字符串(使用hashCode和equals),

30、 没有的话再创建对象C,并将其引用保存在常量池和StingTable中。在此例子中首先会直接在堆中创建对象B;其次,在StringTable中已经发现了“abc”,所以不会购够再创建一个对墨劫称象了C,

31、 并且只会拿到A的引用去创建对象B,为何这么说,反编译的时候看到的(下图234,图4更说明了这一点,new的时候新的对象和原来的对象指向了同一个value数组)。并且最终s2指向的是对象B的引用。

32、 (3)String s3=“abc”,同理这句代码不会创建任何对象,只会将其入口指向s1的入口。

33、 所以最终是创建了两个对象A和B,常量池和StringTable存储的都是对象的引用。

34、 并且A和B的value数组其实是指向同一个地方,即共享一个final的字节数组,且看源码中的String构造方法,如下图4。

35、 在class文件的常量池中,未连接前,字符串变量直接指向的是字符串的值;

36、 连接后指向的是根据此字符串创建的对象的引用。

37、 字符串拼接操作:

38、 String a='ab';

39、 String b='cd';

40、 String c=a+b;//new String(value, 0, count);编译期不可确定,编译器不可优化,执行的时候借助stringBuilder。

41、 String d='abcd';

42、 String e='ab'+'cd';//编译器可以确定,编译器优化

43、 代码String c=a+b;是先创建一个StringBuilder,然后调用StringBuilder的append方法添加a和b,然后再调用其toString,在堆中new了一个对象,

44、 在new对象的时候,会检查常量池是否有“abcd”,有的话,对象的value数组,指向了常量池的引用对应的value的地址,而c则指向堆中的new的对象。

45、 代码String e='ab'+'cd';是直接在常量池生成一个字符串“abcd”,e指向常量池的“abcd”。

46、 下图是StringBuilder的toString,其创建了一个新的对象,并且会拷贝一份value数组。

47、 总结一点,如果字符串拼接的时候有变量,则会使用stringBuilder去处理。否则直接优化。

以上就是string类型这篇文章的一些介绍,希望对大家有所帮助。

  免责声明:本文由用户上传,与本网站立场无关。财经信息仅供读者参考,并不构成投资建议。投资者据此操作,风险自担。 如有侵权请联系删除!

 
分享:
最新文章