Android字符相关

1、String的不可变性

打开String的源码,类注释中有这么一段话

“Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings.Because String objects are immutable they can be shared.”。

这句话总结归纳了String的一个最重要的特点:String是值不可变(immutable)的常量,是线程安全的(can be shared)。

接下来,String类使用了final修饰符,表明了String类的第二个特点:String类是不可继承的。

下面是String类的成员变量定义,从类的实现上阐明了String值是不可变的(immutable)。

 private final char value[];
 private final int count; 

因此,我们看String类的concat(连接)方法。实现该方法第一步要做的肯定是扩大成员变量value的容量,扩容的方法重新定义一个大容量的字符数组buf。第二步就是把原来value中的字符copy到buf中来,再把需要concat的字符串值也copy到buf中来,这样子,buf中就包含了concat之后的字符串值。下面就是问题的关键了,如果value不是final的,直接让value指向buf,然后返回this,则大功告成,没有必要返回一个新的String对象。但是,可惜,由于value是final型的,所以无法指向新定义的大容量数组buf,那怎么办呢?

return new String(0, count + otherLen, buf);

这是String类concat实现方法的最后一条语句,重新new一个String对象返回。这下真相大白了吧!

在讨论String的定义方法之前,先了解一下常量池的概念:

常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。常量池还具备动态性,运行期间可以将新的常量放入池中,String类的intern()方法是这一特性的典型应用。虚拟机为每个被装载的类型维护一个常量池,池中为该类型所用常量的一个有序集合,包括直接常量(string、integer和float常量)和对其他类型、字段和方法的符号引用(与对象引用的区别?读者可以自己去了解)。

String的定义方法归纳起来总共为三种方式:
• 使用关键字new,如:String s1 = new String(“myString”);
• 直接定义,如:String s1 = “myString”;
• 串联生成,如:String s1 = “my” + “String”;这种方式比较复杂,这里就不赘述了

第一种方式通过关键字new定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间,保证常量池中只有一个“myString”常量,节省内存空间。然后在内存堆中开辟一块空间存放new出来的String实例,在栈中开辟一块空间,命名为“s1”,存放的值为堆中String实例的内存地址,这个过程就是将引用s1指向new出来的String实例。

第二种方式直接定义过程:在程序编译期,编译程序先去字符串常量池检查,是否存在“myString”,如果不存在,则在常量池中开辟一个内存空间存放“myString”;如果存在的话,则不用重新开辟空间。然后在栈中开辟一块空间,命名为“s1”,存放的值为常量池中“myString”的内存地址。

String s1 = new String(“myString”);
String s2 = “myString”;
System.out.println(s1 == s2); //结果是false,因为s1指向的是堆中String对象,而s2指向的是常量池中的String常量。

2、StringBuilder和StringBuffer的区别

StringBuffer和StringBuilder都继承了抽象类AbstractStringBuilder,这个抽象类和String一样也定义了char[] value和int count,但是与String类不同的是,它们没有final修饰符。因此得出结论:String、StringBuffer和StringBuilder在本质上都是字符数组,不同的是,在进行连接操作时,String每次返回一个新的String实例,而StringBuffer和StringBuilder的append方法直接返回this,所以这就是为什么在进行大量字符串连接运算时,不推荐使用String,而推荐StringBuffer和StringBuilder。那么,哪种情况使用StringBuffe?哪种情况使用StringBuilder呢?

StringBuffer在方法前加了一个synchronized修饰,起到同步的作用,可以在多线程环境使用。为此付出的代价就是降低了执行效率。因此,如果在多线程环境可以使用StringBuffer进行字符串连接操作,单线程环境使用StringBuilder,它的效率更高。

3、字符集的理解:Unicode、UTF-8、GB2312等

字符集分类:

ASCII编码
ASCII第一次以规范标准的型态发表是在1967年,最后一次更新则是在1986年,至今为止共定义了128个字符;ASCII的最大缺点是只能显示26个基本拉丁字母、阿拉伯数目字和英式标点符号,因此只能用于显示现代美国英语(而且在处理英语当中的外来词如naïve、café、élite等等时,所有重音符号都不得不去掉,即使这样做会违反拼写规则)。一个字节存放一个字符。

ANSI编码
为使计算机支持更多语言,通常使用0x800~xFF范围的2个字节来表示1个字符。比如:汉字 ‘中’ 在中文操作系统中,使用 [0xD6,0xD0]这两个字节存储。
不同的国家和地区制定了不同的标准,由此产生了GB2312,BIG5,JIS等各自的编码标准。这些使用2个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,在日文操作系统下,ANSI 编码代表 JIS 编码。
不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。

Unicode编码
为了使国际间信息交流更加方便,国际组织制定了 UNICODE 字符集,为各种语言中的每一个字符设定了统一并且唯一的数字编号,以满足跨语言、跨平台进行文本转换、处理的要求。
在 UNICODE 被采用之后,计算机存放字符串时,改为存放每个字符在 UNICODE 字符集中的序号。目前计算机一般使用 2 个字节(16 位)来存放一个序号(DBCS,Double Byte Character System),因此,这种方式存放的字符也被称作宽字节字符。比如,字符串 “中文123” 在 Windows 2000 下,内存中实际存放的是 5 个序号,一共10个字节。

Unicode字符集包含了各种语言中使用到的所有“字符”。用来给 UNICODE 字符集编码的标准有很多种,比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig 等。

编码分类:

单字节字符编码
(1)编码标准:ISO-8859-1。
(2)说明:最简单的编码规则,每一个字节直接作为一个 UNICODE 字符。比如,[0xD6, 0xD0] 这两个字节,通过 iso-8859-1 转化为字符串时,将直接得到 [0x00D6, 0x00D0] 两个 UNICODE 字符,即 “ÖД。
反之,将 UNICODE 字符串通过 iso-8859-1 转化为字节串时,只能正常转化 0~255 范围的字符。

ANSI编码
(1)GB2312, BIG5, Shift_JIS, ISO-8859-2。
(2)把 UNICODE 字符串通过 ANSI 编码转化为“字节串”时,根据各自编码的规定,一个 UNICODE 字符可能转化成一个字节或多个字节。
反之,将字节串转化成字符串时,也可能多个字节转化成一个字符。比如,[0xD6, 0xD0] 这两个字节,通过 GB2312 转化为字符串时,将得到 [0x4E2D] 一个字符,即 ‘中’ 字。
“ANSI 编码”的特点:
(1)这些“ANSI 编码标准”都只能处理各自语言范围之内的 UNICODE 字符。
(2)“UNICODE 字符”与“转换出来的字节”之间的关系是人为规定的。

UNICODE编码
(1)编码标准:UTF-8, UTF-16, UnicodeBig。
(2)与“ANSI 编码”类似的,把字符串通过 UNICODE 编码转化成“字节串”时,一个 UNICODE 字符可能转化成一个字节或多个字节。
与“ANSI 编码”不同的是:
(1)这些“UNICODE 编码”能够处理所有的 UNICODE 字符。
(2)“UNICODE 字符”与“转换出来的字节”之间是可以通过计算得到的。
UTF-8编码是一种目前广泛应用于网页的编码,它其实是一种Unicode编码,即致力于把全球所有语言纳入一个统一的编码。
UTF-8用来存储字符串所对应的Unicode的码点,在UTF-8中,0-127之间的码字都使用一个字节来存储,超过128的码字使用2,3甚至6个字节来存储。
所以UTF-8并不是我们所习惯认为的,一个中文两个字节,在UTF-8中,中文一般占三个字节,对于特殊字符可能占更多的字节。

4、正则表达式相关问题

Java正则表达式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值