1.String的数据类型

String 不属于基础类型,基础类型有 8 种:byte、boolean、char、short、int、float、long、double,而 String 属于对象
即引用数据类型

2.String类为啥不能被继承

String类是一个被final修饰的类(源码:public final class String)

3.String的底层实现

其实String的底层就是一个被final修饰的字符数组

  1. private final char value[];
  2. 实例化一个字符串,源码中还有很多构造器
  3. public String(String original) {
  4. this.value = original.value;
  5. this.hash = original.hash;
  6. }

4.String的常用方法

indexOf():返回指定字符的索引。
charAt():返回指定索引处的字符。
replace():字符串替换。
trim():去除字符串两端空白。
split():分割字符串,返回一个分割后的字符串数组。
getBytes():返回字符串的 byte 类型数组。
length():返回字符串长度。
toLowerCase():将字符串转成小写字母。
toUpperCase():将字符串转成大写字符。
substring():截取字符串。
equals():字符串比较。

还有许多的方法,具体的使用查阅API或者查看源码

5.==与equals方法的区别以及equals方法到底是怎么一回事

  • ==对于数据类型的不同作用效果是不同的

基本数据类型:比较的是值是否相同
引用数据类型:比较的是引用是否相同(实际上比较的是地址值)

  1. String s1=new String("person");
  2. String s2=new String("person");
  3. Person p1=new Person();
  4. Person p2=new Person();
  5. System.out.println(p1==p2);//false
  6. System.out.println(a==b);//true
  7. System.out.println(s1==s2);//false
  • equals:其实就是相当于==中引用数据类型的比较

源码

  1. public boolean equals(Object obj) {
  2. return (this == obj);
  3. }
  1. 列:
  1. Person p1=new Person();
  2. Person p2=new Person();
  3. System.out.println(p1.equals(p2));//false

为啥下面这个不是false呢?

  1. String s1=new String("person");
  2. String s2=new String("person");
  3. System.out.println(s1.equals(s2));//true

基于以上这个问题看String源码就可以知道在String类中重写父类Object的equals方法

  1. public boolean equals(Object anObject) {
  2. if (this == anObject) {
  3. return true;
  4. }
  5. if (anObject instanceof String) {
  6. String anotherString = (String)anObject;
  7. int n = value.length;
  8. if (n == anotherString.value.length) {
  9. char v1[] = value;
  10. char v2[] = anotherString.value;
  11. int i = 0;
  12. while (n-- != 0) {
  13. if (v1[i] != v2[i])
  14. return false;
  15. i++;
  16. }
  17. return true;
  18. }
  19. }
  20. return false;
  21. }

6.两个对象hashcode()相同,则equals()也一定为true吗

  1. public class Test01 {
  2. public static void main(String[] args) {
  3. String s1="通话";
  4. String s2="重地";
  5. System.out.println("s1的hashcode:"+ s1.hashCode());
  6. System.out.println("s1的hashcode:"+ s2.hashCode());
  7. System.out.println(s1.equals(s2));
  8. }
  9. }
  10. 结果:
  11. s1hashcode:1179395
  12. s1hashcode:1179395
  13. false

但是两个对象的equals()为true,那么hashcode一定相同。

7.Java中操作字符串的有哪些类

  • String,StringBuffer,StringBuilder
  • String,StringBuffer,StringBuilder三者的区别在于String声明的是不可变的对象,而StringBuffer和StringBuilder是可以在原有的字符串的基础上操作。
  • StringBuffer是线程安全的,但是它的效率是低于StringBuilder

8.String str=”i”与 String str=new String(“i”)一样吗?

不一样, String str=”i”是分配在常量池中,而String str=new String(“i”)是分配在堆内存中

9.String创建对象问题

  • String str=”abc”;

大家肯定都知道都会创建一个对象,但是有没有可能没有创建对象呢?还真有可能,如果常量池中已经存在了”abc”,那么不会创建对象,直接将引用赋值给str.

  • String str=new String(“abc”)又是创建了几个对象呢?1个还是2个?

同样的如果常量池没有abc那么创建2个对象,首先会在常量池中创建一个”abc”,然后执行new操作在堆内存中创建一个 String对象存储”abc”,对象的引用赋值给str。如果有,则创建一个String对象。

  • String str=”abc”+”def”创建几个呢?

涉及到+号问题,当一个字符串由多个字符串拼接成一个字符串时,那它自己也是一个字符串,字符串常量的“+”号连接java虚拟机会在程序编译期将它优化为连接后的字符串,所以在编译时就已经是一个字符串了,因此只会创建一个字符串。没有创建临时的abc和def,这样减轻了垃圾回收器的压力。

  • String str=”abc”+new String(“def”)创建了几个对象呢?

有可能都会说4个,abc,def,String对象和abcdef对象。但是不是全对,如果是创建了几个字符那对象,那就是对的,4个字符串对象。
看源码
1.png2.png3.png
由执行流程可以看出,java虚拟机在编译时创建了一个StringBuilder来进行字符串的拼接,所以有5个对象。
但是呢有些可能会认为有6个,最后的“abcdef”不在常量池中存一份吗?
看代码:

  1. public static void main(String[] args) {
  2. String s="abc"+new String("def");
  3. String s1="abcdef";
  4. System.out.println(s==s1);//false
  5. }

有代码可得:false

10.如何将字符串反转

  • 使用StringBuffer和StringBuilder的reverse()

    1. // StringBuffer reverse
    2. StringBuffer stringBuffer = new StringBuffer();
    3. stringBuffer.append("abcdefg");
    4. System.out.println(stringBuffer.reverse()); // gfedcba
    5. // StringBuilder reverse
    6. StringBuilder stringBuilder = new StringBuilder();
    7. stringBuilder.append("abcdefg");
    8. System.out.println(stringBuilder.reverse()); // gfedcba
  • 自己写一个字符串的反转方法。相信大家都会写。