String简介

前天晚上想干完饭补一补String的笔记,碍于学校渣网,加上笔记本没电,一拖拖到现在… 话不多说!

String定义

public final class String
 implements java.io.Serializable, Comparable<String>, CharSequence {} 

为什么设置为不可变类

主要考虑到效率安全

效率:

1.在早期的JVM实现版本中,被final修饰的方法会被转为内嵌调用以提升执行效率。而从Java SE5/6开始,就渐渐摈弃这种方式了。因此在现在的Java SE版本中,不需要考虑用final去提升方法调用效率。只有在确定不想让该方法被覆盖时,才将方法设置为final。

2.缓存hashcode,String不可变,所以hashcode不变,这样缓存才有意义,不必重新计算

安全:

String常被作为网络连接,文件操作等参数类型,倘若可改变,会出现意想不到的结果

String的创建方式

1. 直接赋值
String str = "hello";
2. 构造器

在堆内存创建对象

String str = new String("hello");

要理解String,得了解JVM内存的栈(Stack)、堆(heap)和方法区。
JVM内存简略分布
堆:

  1. 存储的是对象,每个对象包含一个与之对应的class
  2. JVM只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
  3. 对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定

栈:

  1. 每个线程包含一个栈区,栈中只保存基本数据类型的对象和自定义对象的引用(不是对象)
  2. 每个栈中的数据都是私有的
  3. 栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)
  4. 数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会自动消失

方法区:

  1. 静态区,跟堆一样,被所有的线程共享
  2. 方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量

字符串常量池则位于方法区中

String str1 = "ff";
String str2 = "ff";

System.out.println(str1 == str2); // true

当执行第一句时,JVM会先去常量池中查找是否存在ff,当存在时直接返回常量池里的引用;当不存在时,会在字符创常量池中创建一个对象并返回引用。

当执行第二句时,同样的道理,由于第一句已经在常量池中创建了,所以直接返回上句创建的对象的引用。

String str1 = "ff";
String str3 = new String("ff");System.out.println(str1 == str3); // false

当执行第一句时,JVM会先去常量池中查找是否存在ff,当存在时直接返回常量池里的引用;当不存在时,会在字符创常量池中创建一个对象并返回引用。

执行第二句时,会在堆(heap)中创建一个对象,当字符串常量池中没有‘ff’时,会在常量池中也创建一个对象;当常量池中已经存在了,就不会创建新的了。

String str4 = "lovehuihui";
String str5 = "love" + "huihui";

System.out.println(str4 == str5); // true

由于”love”和”huihui”都是常量,编译时,第二句会被自动编译为‘String str5 = “lovehuihui”;

String str4 = "lovehuihui";
String str6 = "love";
String str7 = "huihui";
String str8 = str6 + str7;

System.out.println(str4 == str8); // false

前三句存储的是常量池中的引用地址

第四句String str8 = str6 + str7;执行时,JVM会在堆中创建一个以str6为基础的StringBuilder对象,然后调用StringBuilder对象的append方法完成和str7的合并。之后会调用toString()方法在堆(heap)中创建一个String对象,并把这个String对象的引用赋给str8

类可变和线程安全

  1. String不可变安全
  2. StringBuffer可变安全
  3. StringBuilder可变非安全

使用选择:

  1. 当有少量连接操作时,使用String
  2. 当单线程下有大量连接操作时,使用StringBuilder
  3. 当多线程下有大量连接操作时,使用StringBuffer

常见题目

String str = new String(“abc”)创建了多少个实例?

分开类的加载和类的执行来讲:

类的加载:

当加载类时,”abc”被创建并驻留在了字符创常量池中(如果先前加载中没有创建驻留过)

类的执行:

当执行此句时,因为”abc”对应的String实例已经存在于字符串常量池中,所以JVM会将此实例复制到会在堆(heap)中并返回引用地址


这篇文章也是以前找了很多篇一起结合整出来的 侵删
有何不妥请多多提出~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值