1、字符串是一个字符序列,但它不是一个基本类型。
2、当我们在java中创建一个字符串时,它实际上创建了一个String类型的对象。
3、String是不可变的对象,这意味着它一旦创建就不能被更改。
因为底层是通过
final
修饰的数组 实现的
4、String是java中唯一支持操作符重载的类。可以使用+操作符连接两个字符串。
例如“a”+“b”=“ab”。
5、Java为字符串操作提供了两个有用的类——StringBuffer
和StringBuilder
。
Different Ways to Create String
1. Using string literal
String str = "abc";
When we create a String using double quotes, JVM looks in the
String pool
to find if any other String is stored with same value. If found, it just returns the reference to that String object else it creates a new String object with given value and stores it in the String pool.
个人批注:
1、关于String pool 不敢翻译,还是英文看着更能体会原意
2、上文应该是基于老版本,Java高版本String pool里存的也是引用了
2. Using new keyword
There are several constructors available in String class to get String from char array,
byte array
, StringBuffer
and StringBuilder
.
String str = new String(new byte[]{65, 97, 48}); //Aa0
String str = new String(new char[]{'A', 'a', '0'}); //Aa0
String str = new String(new int[]{65, 97, 48}, 1, 2); //a0
String str = new String("originalString");
StringBuffer str = new StringBuffer ("Hello");
str.append("World");
StringBuilder str = new StringBuilder("Hello");
str.append("World");
String s1 = "Hello";
String s2 = "World";
s1.concat(s2) String Concatenation
String s3 = s1 + s2; String Concatenation using + Operator
Java String compare
equals()
equalsIgnoreCase()
compareTo()
compareToIgnoreCase()
compareTo()
按照字典(Unicode编码
)索引的顺序进行比较,先找寻两个字符串长度较短
的那个作为比较循环的次数,挨个比较元素str1[i]-str2[i]
循环内如果有结果就输出结果,如果循环过后发现所有的字符都一样,最后用长度去减length1-length2
。
compareToIgnoreCase()
toUpperCase以后,和compareTo一样功能
Java String Methods
split()
contains(CharSequence s)
length()
replace()
format()
substring()
6. Java String Pool
7. String intern() Method
class文件常量池,字符串常量池,运行时常量池,到底是啥?.
String有哪些特性?
-
不变性:
String类中使用字符数组保存字符串。
private final char value[];
因为有“final”修饰符,所以string对象是不可变的。对于已经存在的String对象的修改都是重新创建一个新的对象,然后把新的值保存进去.
数组 value[]存储String中的每一个字符,不可变性体现在两个方面—>长度,内容:
final
—>代表最终的不可改变的—>地址不可变
–>只能指向那块内存空间—>数组的长度是本身不可变的—>所以得到变量value指向固定空间
且空间长度固定
private
—>当前类中才可以访问—>类外部获取不到
数组的值也没有办法给数组赋值—>数组中的内容也不能改变了 -
final:使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性。
-
常量池优化:String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用;
String为什么要设计成不可变的?
- 便于实现字符串池(String pool)
如果每一次声明一个String都创建一个String对象,那将会造成极大的空间资源的浪费. - 使多线程安全
在并发场景下,多个线程同时读一个资源,是安全的,不会引发竞争,但对资源进行写操作时是不安全的,不可变对象不能被写,所以保证了多线程的安全。 - 避免安全问题
在网络连接和数据库连接中字符串常常作为参数,例如,网络连接地址URL,文件路径path,反射机制所需要的String参数。其不可变性可以保证连接的安全性。如果字符串是可变的,黑客就有可能改变字符串指向对象的值,那么会引起很严重的安全问题。 - 加快字符串处理速度
由于String是不可变的,保证了hashcode
的唯一性
,于是在创建对象时其hashcode就可以放心的缓存
了,不需要重新计算。这也就是Map喜欢将String作为Key的原因。在使用 HashMap 的时候,用 String 做 key 有什么好处? 这就是答案
String,StringBuffer,,StringBuilder 的区别是什么?
- 可变与不可变。
String类使用final修饰字符数组保存字符串,故string对象是不可变的
private final char value[];
StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,这两种对象都是可变的。
char[] value;
- 是否线程安全。
String中的对象是不可变的,也就可以理解为常量,显然线程安全。
StringBuilder是非线程安全的。
StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
StringBuffer 1.0版 早期版本 线程同步 安全性比较高 执行效率相对较低
StringBuilder 1.5版 后期版本 线程异步 安全性比较低 执行效率相对较高
字符型常量 和 字符串常量的区别?
1、字符常量是单引号
引起的一个字符,字符串常量是双引号
引起的若干个字符。
2.、字符常量为一个整型值
( ASCII 值),可以参加表达式运算;字符串常量为一个对象,存储的是地址值
(该字符串在内存中存放位置);
3、字符常量只占2个字节
;字符串常量占若干个字节
(至少一个字符结束标志) (注意: char 在Java中占两个字节)。
String str = “abc” 与 String str = new String(“abc”) 一样吗?
不一样,一个new一个对象,一个取String pool查找
new String(“aaa”); 创建了几个字符串对象?
String str=“abc”:0个或1个
new String(“aaa”):1个或2个