String类代表的就是字符串,String类对象创建之后不可变。
- 常用的构造方法
String str = "Hello";//方式1
String str2 = new String("Hello");//方式2
char[] array = {'a', 'b', 'c'};//方式3
String str3 = new String(array);
- 字符串比较
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); //true
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);//false
我们先来分析两种创建字符串的内存分布
这里我们引入字符串常量池,就是专门用来存储字符串常量,常量是不允许修改的,代码中要有多次使用同一个常量我们直接引用常量池里面的,方便很多,不用再创建对象。
注意:常量池在JDK1.7之前是在方法区里面,JDK1.7之后,在堆里面
对于字符串的比较,由于字符串是一个引用类型,我们可以看出==
比较的是地址,想要比较里面的内容我们就要使用String类提供的equals
方法.
String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));//true
关于equals的使用:
System.out.println(str.equals(“hello”));
System.out.println("Hello".equals(str));
//我们经常使用的是第二种方式,因为如果str为空的话,第一种方式会抛出异常,第二种输出“false”
在String类中compareTo()方法是一个非常重要的方法,该方法返回一个整型,该数据会根据大小关系返回三类内容:
- 相等:返回0.
- 小于:返回内容小于0.
- 大于:返回内容大于0
我们进一步理解String类存储方式
String str1="abcdef";
String str2=new String("abcdef");
char[] array={'a','b','c','d','f'};
String str3=new String(array);
String str4="abc"+"def";//编译期间已经确定"abcdef"
String str5="abc"+new String("def");
System.out.println(str1==str2);//false
System.out.println(str1==str3);//false
System.out.println(str1==str4);//true
System.out.println(str1==str5);//false
String str6="abc";
String str7="def";
String str8=str6+str7;
System.out.println(str1==str8);//false
手动入池
String str1="abcdef";
String str2=new String("abcdef");
对于这种情况,无疑产生了空间的浪费,我们可以采用String 的 intern 方法来手动把 String 对象加入到字符串常量池中
String str1 = new String("hello").intern() ;
String str2 = "hello" ;
System.out.println(str1 == str2);//true
字符串不可变
String 类的内部实现也是基于 char[] 来实现的, 但是 String 类并没有提供 set 方法之类的来修改内部的字符数组,如果一定要更改字符串,我们可以利用反射
String str = "hello" ;
for(int x = 0; x < 1000; x++) {
str += x ;
}
System.out.println(str);
对于这样的代码我们中间产生了太多的临时对象,造成了空间的浪费。
为什么 String 要不可变?
- 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了.
- 不可变对象是线程安全的.
- 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
剩下的就是方法的使用我们可以参考文档