• 项目
  • 博客
  • 动态
  • 话题
  • 问答
  • 资讯

java数据类型浅析之字符串(二)

Java

AI-李国瑞·2020-3-3 17:30:17

9
884

这一篇继续介绍java字符串及其深层原理和字符串比较这一困扰我许久的部分,希望大家积极指正

Java字符串.png

一;不可变字符串String 两种创建方式

第一种

String handle = new String([string_content]);
Handle句柄,[]表示可写可不写。

我先分析一下这段代码
1、new String;指的是在堆空间中创建一个String类型对象
2、末尾的([string_content]);调用String类的构造方法初始化值为"string_content"(值随意)
3、String handle;在栈中声明一个String类的,名为"handle"的句柄,注意它不是对象(对象引用)(String类型的句柄只能指向String类型的对象)
4、"="将对象引用指向在堆内存中创建的String类型的对象

基本含义理解后大家再回看这幅图
内存图解.png
例 、创建对象形式
String s= new String(“china”);
先去常量池中找是否有China
若无;则在池中创建一个"china"对象,再去堆中创建一个常量池中的此对象的拷贝对象,再去栈中开辟名为“s”的空间,存放此对象的链接地址。(此时的S,就是句柄)
若有;去堆中创建一个常量池中的此对象的拷贝对象,再去栈中开辟名为“s”的空间,存放此对象的链接地址。

问题1,这段代码String s= new String(“china”);究竟创建了几个String对象?它们分别是?

答案;1或2个,分别是(常量池中的China)和堆中的China,若常量池已有China,则为1
我们继续
String y= new String(“china”);
这个显然是成立的,不会报错,这样我们就得出。一个对象可以有多个(N个)对象的引用
String y= new String(“ShanXi”);
这样对象的引用就会重新指向"ShanXi"。
//y句柄改变了指向,指向了常量池中的ShanXi,而china则会成为虚拟机的垃圾回收机制的对象,在未来的某时被吸收
String y;?在这里声明了一个对象的引用,但并没有明确指向,但编译器不会报错。
综上所述,一个对象的引用可以指向1或0个对象。一个对象可以有N个对象的引用
所以也可以这样表示
String y;
y = new String(“china”);

第二种、直接赋值

2、String d= “china”;
先去常量池中找是否有China
若无;则在池中创建一个"china"对象,再去栈中开辟名为“d”的空间,存放此对象的链接地址。
若有;去栈中开辟名为“d”的空间,存放此对象的链接地址。

问题2,这里创建了几个对象呢?

若常量池中有china,则创造0个对象,反之创造1个对象
所以第二种方式可能创造0或1个对象

第三个问题
String s = “a” + “b” + “c” + “d” + “e”; 创建了几个对象呢?

代码被编译器在编译时优化后,相当于直接定义了一个”abcde”的字符串,所以,上面的代码应该只创建了一个String对象

重要方法intern();

返回字符串对象的规范化表示形式。
用人话说就是获取对象在常量池中的值,当然它还有更深层次的用法,我也不太会….
利用这个方法可以很好理解字符串特别是常量池的概念

String handle3=new String("TYUT"); String handle4=new String("YunDing"); System.out.println(handle3.intern()); System.out.println(handle4.intern());

答案:
TYUT
YunDing

二、可变字符串StringBuffer

由于我对这个接触很少,就总结一下构造方法,其他的方法大家可以自行百度

StringBuffer的构造方法:

StringBuffer():无参构造的形式,初始容量为16
StringBuffer(int capacity):指定容量构造一个字符串缓冲区
StringBuffer(String str):构造一个字符串缓冲区,将指定的字符串内容作为其初始化内容,长度为16加上str的长度
例、

String Buffera=new StringBuffer("abc"); String Bufferb=new StringBuffer(); System.out.println(a.capacity()); System.out.println(b.capacity());

结果分别是19和16

三、(字符串的)比较方法

这一篇先说字符串的,后面再到其他数据类型的比较
两种比较方式“ == ”和equals()
• “==”;分为比较基本数据类型和引用数据类型
基本数据类型比较的是值;引用数据类型比较的是内存地址

• equals();这个方法是Object类中的方法,Object是java默认提供的一个类,如果一个类没有明确指定继承关系,那么它将继承Object,也就是可以使用它规定的方法。
(1)不能比较基本数据类型。
(2)equals()在Object类中是比较对象的内存地址。

public boolean equals(Object obj){
	return(this==obj);
}

而在String类中已经将equals()重写,比较的是对象的值(常量池中的值)

public boolean equals(Object anObject){ if(this == anObject){ return true; } if(anObject instanceof String){ String aString = (String) anObject; if(!COMPACT_STRINGS||this.coder==aString.coder){ return StringLatin1.equals(value,aString.value); } } return false; }

如果理解了之前的内容,只要你不记混这两种比较方式,那你应该理解了字符串的比较。给大家一些例子,可以尝试做一下,后面是输出结果供对照

//先比较newString();产生的 //内容相同,结果第一个false,第二个显然true String handle = newString("ShanXi"); String handle2 = newString("ShanXi");; System.out.println("handle和handle2相等吗?"+(handle==handle2)); System.out.println("handle和handle2相等吗?"+(handle.equals(handle2))); //内容不同,结果显然均为false String handle3 = newString("TYUT"); String handle4 = newString("YunDing"); System.out.println("handle3和handle4相等吗?"+(handle3==handle4)); System.out.println("handle3和handle4相等吗?"+(handle3.equals(handle4))); //再比较直接赋值型 //内容不同,结果显然均为false String handle5 = "java"; String handle6 = "python"; System.out.println("handle5和handle6相等吗?"+(handle5==handle6)); System.out.println("handle5和handle6相等吗?"+(handle5.equals(handle6))); //内容相同,结果显然均为true,因为两者都指向同一个内存地址,位于常量池 String handle7 = "java"; String handle8 = "java"; System.out.println("handle7和handle8相等吗?"+(handle7==handle8)); System.out.println("handle7和handle8相等吗?"+(handle7.equals(handle8))); //混合比较 //内容相同,第一个返回false,因为handle9的地址是在堆中,handle8是在常量池中。第二个返回true String handle9 = newString("java"); System.out.println("handle9和handle8相等吗?"+(handle9==handle8)); System.out.println("handle9和handle8相等吗?"+(handle9.equals(handle8))); //intern()返回字符串对象的规范化表示形式。通俗一点说,就是返回对应这个字符串内容的那个pool里的对象 System.out.println("handle9和handle8相等吗?"+(handle9.equals(handle8.intern()))); //内容不同 String handle10 = newString("js"); System.out.println("handle10和handle8相等吗?"+(handle10==handle8)); System.out.println("handle10和handle8相等吗?"+(handle10.equals(handle8)));

• 输出结果如下:

handle和handle2相等吗?false
handle和handle2相等吗?true

handle3和handle4相等吗?false
handle3和handle4相等吗?false

handle5和handle6相等吗?false
handle5和handle6相等吗?false

handle7和handle8相等吗?true
handle7和handle8相等吗?true

handle9和handle8相等吗?false
handle9和handle8相等吗?true
handle9和handle8相等吗?true

handle10和handle8相等吗?false
handle10和handle8相等吗?false
最后附上参考链接
字符串常量池
字符串拼接内部实现
字符串创建对象面试问题
StringBuffer相关资料

9

  

评论

全部评论 0

最新

暂无评论

关注

关注

粉丝

相关博客推荐