1、String最关键的定义
首先是基本的定义,源码如下图:
定义的几个关键点:
a、类是由final修饰:不可被继承也就不可以被修改,String是最多被使用的地方,是作为Java语言的基石,也是不应该被修改的。同时也便于实现字符串常量池,减少字符串的开销。
b、一个final修饰的char数组:数组保存的是String的内容。同样是被final修饰,不可修改,保证了String的内容不被修改,保证了线程安全之类的问题。
c、一个hash:上面两点保证了String的hash值不会改变,很适合用于Map的键。
2、常见方法
一个不常用但是关键的方法:compareTo()
compareTo()比较的本质就是两个字符串分别从开始一个一个的比较,直到比出大小,所以平时比如数值型字符串、日期型字符串之类的比大小是可以直接比较的。
另外一个方法:join()
把数组或者集合按指定字符串拼接起来,数组、集合里面存储的必须是实现了CharSequence接口的。目前实现了它的只有三个类:String、StringBuffer、StringBuilder。具体使用如下图:
还有几个见名知意的关键方法:
indexOf、lastIndexOf():字符串出现、最后出现的位置。
contains():是否包含指定字符串。
toLowerCase()、toUpperCase():字符串变小写、大写。
replace()、split():替换指定字符串、分割字符串
trim():去掉字符串两边的空格,比如" java "变成“java”
3、工具
一个专门处理String的工具类:org.apache.commons.lang3.StringUtils。它包含了基本所有对String的处理,同时防止了空指针的出现。
StringUtils.isBlank():是否为空,不管是null还是空字符串都是true。
StringUtils.isNotBlank():是否不为空,上一个方法取反。
StringUtils.isAnyBlank():同时验证多个字符串是否为空,任意为空返回true。
StringUtils.isNoneBlank():都不为空,上一个取反。
StringUtils.isAllBlank():所有都是空。
4、面试问题
问题一:==与equals 的区别?
首先看下String的equals
从代码中可以看出是先验证了==,再比较的具体内容。
基本类型的就是纯数值的比较,而对象的表示的是两个变量是否引用的同一个对象。
在Object中的equals就是用来判断的。所以如果类没有重写equals方法那么equals和相同。如果已经重写了equals方法,如果==为true,equals一定对true。equals为true,==不一定为true。
问题二:String\StringBuilder\StringBuffer的区别?
String是不可变的,拼接字符串性能比较慢。StringBuilder与StringBuffer也是用来拼接字符串的,他们都比String性能更好(不会新建对象)。
StringBuffer的方法都是用synchronized修饰的,在多线程环境更加安全,但是性能也就比StringBuilder慢点。
不过多个字符串直接拼接不用去创建StringBuilder\StringBuffer再来拼接,底层已经优化。比如"a"+“b”+“c”+"d"并不会创建多个String对象,只有多次拼接,尤其是在循环中拼接字符串最好创建StringBuilder来接收。
问题三:缓存池相关的问题
如图:
打印结果为false,false,true。
a是new一个对象出来,和平常的对象一样。b就是JVM对String的优化了。他会先去String的常量池去查,没有就在常量池先创建一个,后面的相同字符串都指向常量池中的这个对象。c就是上一步说的JVM对String的优化了。c和b都是指向的常量池的String。
这里有一个String的方法intern(),他可以把a的值加入到常量池。不过a仍然是一个没有在常量池的对象。他只是把"abc"这个字符串加到了常量池。
Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!