上一章,初步了解了String对象,知道它能用来定义一个字符串变量,本章主要学习String、StringBuilder的方法,以及如何通过API来查找对象和方法的用法。
先来了解下String中常用的方法:
public class Test {
public static void main(String[] args) {
String str = " 123456aBCDef哈哈 "; //定义一个字符串变量
System.out.println(str.charAt(6)); //返回指定索引处的char值
System.out.println(str.indexOf("6a")); //返回指定子字符串在此字符串中第一次出现处的索引。
System.out.println(str.indexOf("6a1")); //返回指定子字符串在此字符串中第一次出现处的索引。不存在时返回-1
System.out.println(str.startsWith("123")); //测试此字符串是否以指定的前缀开始。
System.out.println(str.endsWith("e")); //测试此字符串是否以指定的前缀结束。
System.out.println(str.length()); //返回此字符串的长度
System.out.println(str.replaceAll("6a", "!!!")); //用!!!替换6a,第一个参数为正则表达式
System.out.println(str.substring(3, 10)); //截取指定范围索引的字符串
System.out.println(str.toLowerCase()); //转小写
System.out.println(str.toUpperCase()); //转大写
System.out.println(str.trim()); //前后去空格、回车等不可见字符
System.out.println("---------------------------------------");
String arr[] = "abc,123,sss,666,sisia9".split(","); //根据匹配给定的正则表达式来拆分此字符串返回数组。
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
这些方法非常常用,假如我们在使用一个对象时,不知道它里面有哪些方法可以被我们使用,就需要通过查询API帮助文档来获取对象的使用方法。
下载一个JDK_API_1_6_zh_CN.CHM。https://pan.baidu.com/s/1XwtYFaytZFi_YX1pPd6qeg
,打开之后点“显示”
,然后点“索引”,输入“String”,按回车,选择第一个,之后就是如下界面:
然后往下翻,找到摘要方法,选一个你想了解的方法,如charAt,点击进去
public char charAt(int index),可以看到该方法的返回值以及传参类型:返回一个char型字符,需要传入一个int型的值,文档里面写的都很清楚,遇到不会的方法就多查API就对了。
下面的内容很重要
下面是定义String的两种方式
public class Test {
public static void main(String[] args) {
String str1 = "我是一个字符串"; //第一种方式
String str2 = "我是一个字符串";
String str3 = new String("我是一个字符串"); //第二种方式
System.out.println("str1==str2 " + (str1 == str2));
System.out.println("str1==str3 " + (str1 == str3));
}
}
运行之后,能看到用三个变量定义同一个字符串,str1等于str2,str1不等于str3,为什么呢?
我们定义字符串对象str3时候会把str3对象保存在堆里,把堆的引用保存在栈里,如图:
绝大多数对象的创建就是这么个过程
但是字符串对象是个例外,他还维护了一个字符串常量池,如在定义str1时,他先在常量池种找有没有“我是一个字符串”,(1)如果没有就创建一个,然后在栈中建一个str1并保存常量池的引用。(2)如果有就直接在栈中建一个str1,然后在栈中建一个str1并保存常量池的引用。str2同上。对于str3的定义方式,因为使用了new关键字,就一定会在堆中创建一个对象,存在一个一对一的关系,然后常量池也会创建一个对象(如果这个对象“我是一个字符串”已存在,就不创建了,直接指向就可以了)。str1和str2的创建是一对多的关系。
我们用“==”比较对象时,是比较对象的引用(或理解为对象的地址),如上图所示,str1和str2都是指向常量池中的同一个对象,所以他们的引用相同,返回true,str3是在堆中新建了一个对象,与str1的引用不相同,所以返回false。面试题中经常会问String str = new String("abc")创建了几个对象,答案是:两个,一个在堆中,一个在常量池中。
那么,我们应该怎么比较字符串呢?String给我们提供了一个方法:equals(),专门用来比较字符串中的指,而非比较地址。代码如下:
public class Test {
public static void main(String[] args) {
String str1 = "我是一个字符串";
String str2 = "我是一个字符串";
String str3 = new String("我是一个字符串");
System.out.println("str1==str2 " + str1.equals(str2));
System.out.println("str1==str3 " + str1.equals(str3));
System.out.println("123".equals("321"));
}
}
System.out.println("123".equals("321"));
}
}
同理,我们定义一个字符串之后,每次改变值时,也会有一个查找或创建常量池的过程,这个过程会有一定的耗时,假如你频繁的改变str1值或者一直追加str1值的时候,使用String类就不划算了。下面代码可以得出这个结论:
public class Test {
public static void main(String[] args) {
String str1 = "";
long begin = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
str1 = str1 + i;
}
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - begin));
}
}
给str1追加一万次和十万次所用的时间相差还是比较大的,一个0.189秒,一个32秒多。
这个时候我们就可以用StringBuilder来解决。StringBuilder是也是对字符串操作的一个对象,只不过他改变值或追加值的时候不会改变对象的引用,所以效率就很快。
public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
long end = System.currentTimeMillis();
System.out.println("用时:" + (end - begin));
}
}
十万次的追加只用了0.04秒。
StringBuilder的一般用法:
public class Test {
public static void main(String[] args) {
StringBuilder sb1 = new StringBuilder();
sb1.append("我");
sb1.append("是");
sb1.append("一个");
sb1.append("字符串").append("哦也").append("!!!");// 看,它也可以连续.出来。
System.out.println(sb1.toString());
//他其实更适合用在多次循环中,循环次数也多效率体现的越明显(与String相比)
StringBuilder sb2 = new StringBuilder();
for (int i = 0; i < 2; i++) {
if (i == 0) {
for (int j = 0; j < 26; j++) {
sb2.append((char)(j + 97)).append(" ");
}
}
else {
sb2.append("\r\n");
for (int j = 0; j < 26; j++) {
sb2.append((char)(j + 65)).append(" ");
}
}
}
System.out.println(sb2.toString());
}
}
数字与字符互转相见百度百科:https://baike.baidu.com/item/ASCII/309296?fr=aladdin&fromid=19660475&fromtitle=ascii%E7%A0%81%E8%A1%A8
StringBuilder中的其他常用方法自行查看API即可。
上节作业答案:
public class C {
int c = 4;
public int c (int num) {
return c * num;
}
}
public class B {
float b = 23.432f;
public void b() {
C c = new C();
int num = c.c(618);
System.out.println(num);
}
}
public class A {
public static void main(String[] args) {
B b = new B();
System.out.println(b.b);
b.b();
}
}