小瓜牛漫谈 — String
来源:互联网 发布:淘宝天猫买药可靠吗 编辑:程序博客网 时间:2024/05/21 21:33
String 类在 Java 中代表字符串。Java 程序中的所有字符串字面值(如 "abc" )都作为此类的实例实现。
public static void main(String[] args) { String str1 = "abc"; String str2 = new String("cde"); System.out.println(str1); System.out.println(str2); }
在上面代码中, 第 4 行实际上创建了两个 String 对象, 一个是 "cde" 本身, 另外一个则是由 new 关键字为对象申请开辟的内存空间。
[ 可结合文章最下面给出的第 10 条来理解 ]
通常, 使用 String(String original) 构造器来创建 String 对象要比直接使用字符串字面值的开销更加的大。
package net.yeah.fancydeepin.string; public class Application { public static void main(String[] args) { String str = "abc"; str += "cde"; System.out.println(str); } }
当程序运行时, JVM 内存中的分配看起来应该像:
从上面的图来看, str 最初引用的是 "abc" 对象, 最终打印输出的结果是 abccde, 这并不是说 str 所引用的对象的内容发生了变化,
而是 str 在执行的过程中重新引用了另外的一个 String 对象 "abccde"。
从上面的图来看:
第 0 行, 将常量池中的 "abc" 对象压栈;
第 8 行, 调 String.valueOf(Object obj) [ 实际上是将 str 转成了 String 对象 ];
第 3、11 行, 是在创建 StringBuilder 对象, 通过 StringBuilder(String str) 构造器 [ 参数是第 8 行的 String 对象 ];
第 14 行, 将常量池中的 "cde" 对象压栈;
第 16 行, 调 StringBuilder 的 append 方法 [ 将 "cde" 拼在 "abc" 的后面 ];
第 19 行, 调 StringBuilder 的 toString() 方法。
使用 jad 工具, 可以更加容易的去读懂编译后的字节码文件内容: jad -o -a -s .java Application.class
结合上面的图可以看出, 在 java 中, 通过使用 "+" 符号来串联字符串的时候, 实际上底层会转成通过 StringBuilder 实例的 append() 方法来实现。
[ 关于对 String 类使用 "+" 符号来串联字符串, 在文章最下面的第 10 条继续来补充。 ]
String 类常用方法:
1> startsWith(String prefix)、endsWith(String suffix)
startsWith(prefix) 测试字符串是否是以指定的前缀 prefix 开始, endsWith(suffix) 测试字符串是否是以指定的后缀 suffix 结束:
public static void main(String[] args) { String url = "/small-snail/archive/20130421.html"; System.out.println(url.startsWith("/small-snail/archive/")); //true System.out.println(url.endsWith(".html")); //true System.out.println(url.startsWith("/small-snail/category/")); //false System.out.println(url.endsWith(".php")); //false }
2> equals(Object anObject)
在 java 中, Object 是一个顶级类, 所有类都直接或间接或默认的继承了该类。
Object 类有一个 equals(Object obj) 方法, 因此, 所有类都默认的拥有了这个方法。
但 Object 的 equals(obj) 方法默认比较的是两个引用变量所引用的对象是否相同, 只有当两个引用变量引用了相同的一个对象的时候才会返回 true。
String 类重写了 Object 类的此方法, String 类的 equals 方法比较的是两个 String 对象的内容是否相同。
package net.yeah.fancydeepin.string; public class Application { public static void main(String[] args) { String kitty1 = new String("HelloKitty"); String kitty2 = new String("HelloKitty"); StringBuilder kitty3 = new StringBuilder("HelloKitty"); System.out.println(kitty1.equals(kitty2)); //true System.out.println(kitty1.equals(kitty3)); //false } }第 11 行, 虽然 kitty3 的内容与 kitty1 的内容一样, 但由于 kitty3 不是一个 String 对象, 因此调 equals 方法的返回值为 false。
3> equalsIgnoreCase(String anotherString)
比较两个 String 对象的内容是否相同, 忽略大小写。
public static void main(String[] args) { String param1 = "helloKitty"; String param2 = "HelloKitty"; System.out.println(param1.equals(param2)); //false System.out.println(param1.equalsIgnoreCase(param2)); //true }
4> getBytes(String charsetName)、String(byte[] bytes)
getBytes(String charsetName) 是使用指定的字符集 charset 将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中。
package net.yeah.fancydeepin.string; import java.io.UnsupportedEncodingException; public class Application { public static void main(String[] args) throws UnsupportedEncodingException { String param = "哈喽Kitty"; String charset; charset = new String(param.getBytes("GBK")); //乱码 System.out.println(charset); charset = new String(param.getBytes("GB2312")); //乱码 System.out.println(charset); charset = new String(param.getBytes("ISO-8859-1")); //乱码 System.out.println(charset); charset = new String(param.getBytes("UTF-8")); //正常 System.out.println(charset); charset = new String(param.getBytes("UTF-16")); //乱码 System.out.println(charset); } }
上面给出来的是 java 开发过程中比较经常遇到的字符集编码。当一个字符串中含有中文字符的时候, 如果该字符串在编码和解码前后所使用的字符编码不一致,
就会导致中文乱码的问题。
由于我的 eclipse SDK 工作区所使用的是 UTF-8 编码, 所以上面只有 "UTF-8" 字符编码输出的内容是正常的, 其他情况就会出现中文乱码的问题。
5> getBytes(String charsetName)、String(byte[] bytes, String charsetName)
上面示例中出现了中文乱码问题, 其实现在网络上关于中文乱码这点事儿, 资料已经是非常的多了。下面接下来将首先模拟出一个中文乱码的问题, 然后来解决它:
package net.yeah.fancydeepin.string; import java.io.UnsupportedEncodingException; public class Application { public static void main(String[] args) throws UnsupportedEncodingException { String param = "哈喽Kitty"; param = new String(param.getBytes("UTF-8"), "ISO-8859-1"); //中文乱码 System.out.println(param); //解决中文乱码 param = new String(param.getBytes("ISO-8859-1"), "UTF-8"); //恢复正常 System.out.println(param); } }
param = new String(param.getBytes("UTF-8"), "ISO-8859-1"); 意思是说:
将 param 以 UTF-8 编码方式去编码, 然后再按 ISO-8859-1 编码方式去解码编码后的内容, 来构造一个新的 String 对象 param。
由于 param 原本是按 UTF-8 编码方式编码出来的, 现在却使用 ISO-8859-1 编码方式去解码, 这个时候出现中文乱码是很正常的事情。
再者, ISO-8859-1 的编码方式本身是不支持中文的。
解决中文乱码问题, 无非就是使用正确的字符集编码去解码字符串的内容:
param = new String(param.getBytes("ISO-8859-1"), "UTF-8");
首先是将 param 以 ISO-8859-1 的编码方式编码出来, 因为在 java 的 JVM 中, 任何 String 都是一个 unicode 字符串,
接着再使用 UTF-8 去解码, 这个时候的中文就不再是乱码啦。。
为了避免引起误解, 补充说明一下, 上面不是一定要使用与 IDE 相同的编码方式 UTF-8 才不会引起中文乱码, 实际上也可以换成 GBK、GB2312 等兼容中文的
编码方式也是可以的, 只需要保证编码和解码使用的是相同的字符集编码方式即可。
6> indexOf(String str)、lastIndexOf(String str)、substring(int beginIndex, int endIndex)
indexOf 用于返回指定的子字符串在主字符串中第一次出现处的索引值; lastIndexOf 用于返回指定的子字符串在主字符串中最后一次出现处的索引值。
substring 则是用来切割主字符串, 根据开始索引值和结束索引值切割并返回一个新字符串。
package net.yeah.fancydeepin.string; public class Application { public static void main(String[] args) { String param = "archive.logo.ico"; int firstIndex = param.indexOf("a"); int lastIndex = param.lastIndexOf("o"); int length = param.length(); System.out.println(firstIndex); // 0 System.out.println(lastIndex); // 15 System.out.println(length); // 16 System.out.println(param.substring(firstIndex, lastIndex)); // archive.logo.ic param = param.substring(param.lastIndexOf("."), length); // .ico System.out.println(param); } }
从上面代码可以看出, 索引值是从 0 开始的, substring(beginIndex, endIndex) 方法切割字符串的区间其实是左闭右开: [ beginIndex, endIndex )
7> replaceAll(String regex, String replacement)
用子字符串 replacement 来替换主字符串中所有由正则表达式 regex 匹配的子字符串。
package net.yeah.fancydeepin.string; public class Application { public static void main(String[] args) { String packageName = Application.class.getPackage().getName(); String packagePath1 = packageName.replaceAll(".", "/"); //将所有的字符换成了'/' System.out.println(packagePath1); // 打印 /////////////////////////// String packagePath2 = packageName.replaceAll("\\.", "/"); //将所有的'.'换成'/' System.out.println(packagePath2); // net/yeah/fancydeepin/string String packagePath3 = packageName.replaceAll("e+", "E"); //凡是出现'e'一次或以上的用'E'替换 System.out.println(packagePath3); // nEt.yEah.fancydEpin.string } }
上面代码中需要注意的是 packagePack1, replaceAll 的第一个参数使用的是正则表达式, 正则表达式中的 '.' 可以匹配除“\n”之外的任何单个字符,
因此 packagePath1 打印输出的全是反斜杠'/', 如果要匹配'.', 则应该使用转义字符, 像上面代码中的 packagePath2。
8> split(String regex)
根据给定的正则表达式 regex 将主字符串拆分成一个字符串数组。
package net.yeah.fancydeepin.string; public class Application { public static void main(String[] args) { String param = "Java,Android,PHP,C,C++,C#"; String[] languages = param.split(","); for(String language : languages){ System.out.println(language); } } }
9> trim()
忽略字符串的前导空白和尾部空白。
public static void main(String[] args) {2 3 String param = " Hello Kitty ";4 System.out.println(param.trim()); //Hello Kitty5 }
从上面示例可以看出, 调 trim() 方法只是会忽略字符串的前导空白和尾部空白, 对于串中间的空白是不会被处理的。
- 小瓜牛漫谈 — String
- 小瓜牛漫谈 — String、StringBuffer、StringBuilder
- 漫谈
- 漫谈
- 科技漫谈——无人机
- 漫谈系列—大数定律
- WinSocket模型的探讨——漫谈
- WinSocket模型的探讨——漫谈
- MFC漫谈(一)——RTTI
- 一月漫谈——《业务员与玩家》
- 漫谈递归——一步一步算法篇
- 漫谈递归——递归的思想
- c语言——指针漫谈
- 射频识别技术漫谈(2)—国际标准
- Windows 线程漫谈——界面线程和工作者线程
- Windows 线程漫谈——界面线程和工作者线程
- 把握我们的优势——漫谈中国企业管理软件
- Windows 线程漫谈——界面线程和工作者线程
- GPS 真实数据
- 14 C# 第十三章 事件和委托(一) 多播委托的问题
- 实验7
- MyEclipse&Eclipse 默认工作区设置
- oracle 中 dual 详解
- 小瓜牛漫谈 — String
- android.view.WindowManager$BadTokenException: Unable to add window异常
- JAVA的MAP的使用
- 关于“IT学子成长指导”专栏及文章目录
- StringBuffer和StringBuilder
- 国际劳动节
- 分治算法基本思想和典型案例
- 浅谈“囫囵吞枣”
- 基于gpu与cuda c的神经网络实现