java基础之String

162 阅读2分钟

String可能是我们在平常使用中遇到概率最高的一个类了。今天我们就来聊聊关于这个类的一些常见坑位。

一、对象创建

首先来看下关于这个类的定义(jdk1.8版本):

由此我们可以得知:

1.String类不能被继承,因为类使用了final修饰
2.String的值存储是使用的char数组实现的
3.String的值不能被修改,因为char数组被final修饰

二、String、StringBuffer、StringBuilder的区别

1.值是否可变:

		1String是不可变
        2)StringBuilder和StringBuffer是可变的(其内部的字符数组没有使用final修饰)

2.是否线程安全:

		1String中的对象是不可变的,也就可以理解为常量,是线程安全。
        2)StringBuffer 中的方法大都采用了synchronized 关键字进行修饰,因此是线程安全的
        3)StringBuilder 没有采用了synchronized关键字进行修饰,可以被认为是非线程安全的

三、常见问题

例子1:

     public static void main(String[] args) {
            String a="jack";
            String b="jac"+"k";
            System.out.println(a==b);
     }
     这个输出的是true.我们可以来看一下编译后的代码:
     public static void main(String[] args) {
        String a = "jack";
        String b = "jack";
        System.out.println(a == b);
    }

当执行String a="jack"时,JVM首先会去字符串池中查找是否存在"jack"这个字面值的对象。如果不存在,则在字符串池中创建"jack"这个对象,然后将这个对象的引用地址返回给字符串常量a,这样a会指向池中"jack"这个字符串对象;如果存在,则不创建任何对象,直接将池中"jack"这个对象的地址返回,赋给字符串常量。当创建字符串对象b时,字符串池中已经存在"jack"这个对象,所以直接把引用地址返回给b,这样b也指向了池中"jack"这个对象。因此输出:true

例子2:

		String name1=new String("rose");
    	String name2=new String("rose");
    	System.out.println(name1==name2);(输出false)

这个执行的输出是false。因为使用new关键字新建对象的时候,是直接在堆上创建出对象的,不会比较对象的值是否已经存在。因而name1和name2的指向地址是不一样的。

例子3:

   public static void main(String[] args) {
      String a="ja";
      String b="c"+"k";
      String c=a+b;
      System.out.println(c=="jack");(输出false)
      String d="ja"+"ck";
      System.out.println(d=="jack");(输出true)
   }

这里要注意的是,对于d而言,编译器就可以确定d的值是"jack",因而会相等。而c的赋值是在运行起才能确定,其实是对其进行new的处理。所以c的对象是创建在堆中的,所以和字符串"jack"不相等。