我们现在开始学习的就是一些工具类
这些工具类只需要我们学会查阅帮助文档进行开发就可以实现很多功能
例如:我们查看工具类String
关于java JDK中内置的一个类:java.lang.String
1、String表示字符串类型,属于引用数据类型,不属于基本数据类型
2、在java中随便用“双引号”括起来的都是String对象。
例如:"abc" "Hello World" ,这两个是String对象
3、java中规定,双引号括起来的字符串,是不可变的,也就是说"abc"从出生到死亡,不可能变成"abcd"
4、在JDK中,双引号括起来的字符串
例如:"abc" "Hello World",都是直接存储在"方法区" 的 "字符串常量池" 中(JDK8中字符串常量池在堆中)
5、JAVA的lang包路径下的东西不需要导包也可以用,这是SUN公司给lang包的权限
提问 :为什么SUN公司把字符串存储在一个"字符串常量池"中呢?
原因:字符串在实际的开发中使用太频繁,目的是为了提高效率
以下是JVM示图:
第一步:方法区中首先进行类加载,类加载进入到方法区中
第二步:程序执行,main主方法会执行,栈区会压入一个main方法栈帧,在栈帧中,引用类型String s1变量中存储的不是引号的内容,其实是引号的内容的内存地址,引号的内容就是字符串,这些字符串常量存储在方法区中的字符串常量池(JDK8中字符串常量池在堆中)
第三步:在main方法栈帧中,引用类型String s2变量中存储的也是内存地址,此时在字符串常量池中,"abcdef"直接从字符串常量池中提取,"xy"从字符串常量池中新建,"abcdefxy"也从字符串常量池中拼接新建,最终被s2存储的内存地址指向"abcdefxy"
代码演示:
public class StringTest01 {public static void main(String[] args) {String s1="abcdef";String s2="abcdef"+"xy";}
}
以下是代码演示:
public class StringTest01 {public static void main(String[] args) {//下面这两行代码表示底层创建了3个字符串对象,都在字符串常量池中String s1="abcdef";String s2="abcdef"+"xy";//下面演示的是调用String的构造方法//new一个对象就是调用构造方法//分析这个代码中的"xy"是从哪里来的?//凡是双引号括起来的都在字符串常量池中有一份//new一个对象的时候一定在堆内存中开辟空间String s3=new String("xy");}
}
以下是用new对象时对字符串常量池引用(间接引用)的不同
下面再举一个例子:
代码如下:
验证:s1和s2的内存地址是否相同
public class StringTest02 {public static void main(String[] args) {String s1="hello";String s2="hello";System.out.println(s1==s2);}
}
JVM示意图:
原因:
"hello" 是存储 在方法区的字符串常量池中 ,所以"hello"不会新建
== 比较的是变量中保存的内存地址
下面再举一个例子:
public class StringTest02 {public static void main(String[] args) {String s1="hello";String s2="hello";System.out.println(s1==s2);String x=new String("xyz");String y=new String("xyz");System.out.println(x==y);}
}
JVM示意图:
原因:
如上
结论:
字符创对象之间比较不能使用==
== 不够保险,应该调用String类的equals方法
发现:Object类中并没有重写equals方法,于是乎我们找到String类中equals,发现SUN公司已经对它进行重写了
接下来我们对其重写进行测试:
public class StringTest02 {public static void main(String[] args) {String s1="hello";String s2="hello";System.out.println(s1==s2);String x=new String("xyz");String y=new String("xyz");System.out.println(x==y);System.out.println(x.equals(y));String k=new String("testString");System.out.println("testString".equals(k));System.out.println(k.equals("testString"));}
}
为什么:"testString" 这个字符串后面可以加 " . " 呢?
因为:"testString"是一个String字符串对象,只要是对象都能调用方法
这两句有什么区别呢:
System.out.println("testString".equals(k));System.out.println(k.equals("testString"));
建议使用第一种方式,可以避免空指针异常(当一个对象不存在时又调用其方法会产生异常,例如变量k就可能是空指针)