javase -- java常用类-String(含堆)


String(字符串).

  • final类:不可被继承,不可变的字符序列
  • 支持序列化
  • 可以比较大小
  • 字符串是常量,用双引号表示,其值不可更改(String a = “1”; ==> String a = “12”; 这个不叫更改字符串,只是更改字符串引用指向另一个常量,也就是重新赋值)
    • 不会在内存区域进行修改
    • 看似的修改操作(赋值,连接,replace()等),都是会重新指定内存区域的
  • JDK1.8及以前字符内容是存储在一个字符数组private final char value[]
  • JDK1.9及以后字符内容是存储在一个字节数组private final byte value[]
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence,
               Constable, ConstantDesc 

1、定义方式.

  • 字面量定义
  • new
//字面量
String str1 = "abc";
String str2 = "abc";
str1 == str2 //true : ? ==> 字面量是存储常量池中的,常量池中不会存储相同内容的字符串,所以这两个变量指向同一个常量(地址)

//new 
//带参:字符串
String str3 = new String("s");
String str4 = new String("s");
str3 == str4 //false : ? ==> 创建了两个对象,这两个对象是不同的内存空间

//无参
String str5 = new String();// 长度为0的字符串

//带参:char[]
char[] ch;
String str6 = new String(ch);
//String str6 = new String(char[] ch, int startIndex, int count);

//带参: byte[]
byte[] b;
String str7 = new String(b);

//带参:StringBuffer or StringBuilder
String buf = new String(new StringBuffer("11"));
String buf = new String(new StringBuilder("22"));

     ...
     ...
     ...

2、基本方法使用.

常用方法.

1.int length().

返回字符串的长度

2.char charAt(int index).

返回某索引处的字符

3.boolean isEmpty().

判断字符串是否为空字符串

  • “”
  • new String();
  • new String(“”)

boolean isBlank() JDK11 可以判断字符串是否是空串或是空白的

4.String toLowerCase().

将String中所有字符转为小写

5.String toUpperCase().

将String中所有字符转为大写

6.String trim().

返回字符串的副本,忽略前导空白和尾部空白

7.boolean equals(Object obj).

比较字符串的内容是否相同

8.boolean equalsIgnoreCase(String anotherString).

忽略大小写比较内容是否相等

9.String concat(String str).

将指定字符串拼接到字符串的结尾。 等价于 +

10.int compareTo(String anotherString).

比较字符串的大小

11.String subString(int beginIndex).

返回一个新字符串,从索引beginIndex开始截取的字符串

12.String subString(int beginIndex,int endIndex).

返回一个新字符串,从索引 beginIndex开始截取到索引endIndex-1的字符串(左闭右开[beginIndex,endIndex) )

13.boolean endsWith(String suffix).

测试次字符串是否以指定后缀结尾

14.boolean startsWith(String prefix).

测试次字符串是否以指定前缀结尾

15.boolean startsWith(String prefix, int toffset).

测试此字符串从指定索引(toffset)开始的子字符串是否以指定前缀(prefix)开始

16.boolean contains(CharSequence s).

当且仅当此字符串包含指定char值序列时,返回true

17.int indexOf(String str).

返回指定的子字符串在此字符串中第一次出现处的索引

17.int indexOf(String str, int fromIndex).

返回从指定索引开始,指定子字符串str此字符串子串中第一次出现的索引

18.int lastIndexOf(String str).

同上,但是是最后一次

18.int lastIndexOf(String str, int fromIndex).

同上,但是是最后一次

17、18如果方法没有找到,放回都是 -1

19.String replace(char oldChar,char newChar).

返回一个新字符串,会用新字符newChar 替换 旧字符oldChar

20.String replace(CharSequence target, CharSequence replacement).

字符序列的替换 ,字符序列用””表示

21.String replaceAll(String regex, String replacement).

使用指定的replacement替换匹配给定的正则表达式regex的所有子字符串

22.String replaceFirst(String regex, String replacement).

使用指定的replacement替换匹配给定的正则表达式regex的第一个子字符串

23.boolean matches(String regex).

告知此字符串是否匹配给定的正则表达式

24.String[] split(String regex).

根据给定的正则表达式的匹配拆分字符串

25.String[] split(String regex, int limit).

根据匹配给定的正则表达式来拆分字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中

3、字符串与包装类、基本类型之间的转换.

略,详情看 包装类

4、字符串与字符数组之间的转换.

char[] ch = {'1','2'};
//字符数组 --> 字符串
//1.String 构造器 String(char[]) 和 String(char[], int offset, int length)
String s = new String(ch);
String str = "12";
//字符串 --> 字符数组
//1. toCharArray
char c = str.toCharArray();

5、字符串与字节数组的之间的装换.

byte[] b = {1,2};
//字节数组 --> 字符串
//1. Arrays.toString
String str1 = Arrays.toString(b);

//2. 构造器
String str2 = new String(b,"utf-8");
String str = "12";
//字符串 --> 字节数组
//1. getBytes()
byte[] b = str.getBytes("utf-8");

补充.

1、String str1 = “abc”; 与 String str2 = new String(“abc”);的区别?.

  • 前者 变量直接指向内存中常量池里的”abc”(”abc”作为一个对象保存在常量池中)
  • 后者 变量指向新创建的String类型的对象,对象的属性value是指向内存中常量池里的”abc”

2、String str = new String(“a”);在内存中创建了几个对象.

  • 两个
    • 堆内存中new的String对象
    • value属性对应常量池中的数据

3、不同拼接操作的对比.

  • 字面量(常量)之间的连接结果,相当于还是在常量池中声明
  • 有变量名参与的连接结果,会在堆上开辟空间,都相当于new
  • intern()的返回值都在常量池中
String s1 = "hello";
String s2 = "world";

String s3 = "hello" + "world";
String s4 = "helloworld";
String s5 = "hello" + s2;
String s6 = s1 + "world";
String s7 = s1 + s2;
String s8 = s5.intern();//得到的返回值 在常量池中 (不管s5的定义方式)

System.out.println(s3 == s4);//true
System.out.println(s3 == s8);//true
System.out.println(s4 == s8);//true
//其余的比较都是false

final String s9 = "hello";// s9 是常量,常量和常量之间的连接的结果是在常量池中的

4、三种JVM.

  • Sun公司的HotSpot

    • 被Oracle收购

  • BEA公司的JRockit

    • 被Oracle收购
  • IBM公司的J9 VM

5、Heap堆.

一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保证所有引用类型的真实信息,以方便执行器执行,堆内存分为三部分

  • Young Generation Space 新生区
  • Tenure Generation Space 养老区
  • Permanent Space 永久存储区 相当于 方法区

6、Method Area方法区.

和堆一样,是各个线程共享的内存区域,它用于存储虚拟机加载的:类信息、普通常量、静态变量、编译器编译后的代码等,虽然JVM规范将方法区描述为堆的一个逻辑部分,但是它却还有一个别名叫 Non-Heap(非堆)。目的是将其和堆分开

对于HotSpot虚拟机来说,把方法区称为 永久代,但严格本质上锁两者是不同的,或者说使用永久代来实现方法区而已,永久代是方法区的一个实现JDK1.7的版本中,已经将原本放在永久代的字符串常量池移走了

常量池(Constant Pool)是方法区的一部分,Class文件除了有类的版本、字段、方法、接口等描述信息,还有一项信息就是常量池,这部分内容将在类加载后进入方法区的运行时常量

7、新生区.

新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后的被垃圾回收器收集,结束生命。

新生区分为两部分

  • 伊甸区(Eden Sapce):所有的类都是在这new出来的
  • 幸存者区(Survivor Space):
    • s0区
    • s1区

当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不在被其他对象所引用的对象进行销毁。

然后将伊甸园中的剩余对象移动到幸存0区,若幸存0区满了,再对该区也进行垃圾回收,然后移到幸存1区。

如果幸存1区也满了呢?

在移动到养老区,若养老区也满了,那么这个时候将产生Major GCFullGC),进行养老区的内存清理。

若养老区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常(OutOfMemoryError

如果出现java.lang.OutOfMemoryError:java heap space 异常,说明java虚拟机的堆内存不够。原因:

  • Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整
  • 代码中创建了大量大对象,并且长时间不能被垃圾回收器收集(存在被引用)。—- 内存溢出;内存泄露

8、永久区.

永久存储区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收调度,关闭JVM才会释放掉此区域所占的内存

如果出现java.lang.OutOfMemoryError: PermGen Space 异常,说明java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。

  • 列如,在一个tomcat下部署了太多的应用,或者大量动态反射生成的类不断被加载,最终导致Perm区被占满

字符串常量池

JDK1.6及以前 常量池分配在永久代,1.6在方法区

JDK1.7有,但是已经逐步 “去永久代”,1.7在堆

JDK1.8及以后无,1.8在元空间(MetaSpace)

9、编码和解码.

编码:String –编码字符集utf-8–> 字节 (保存数据,传输数据)

解码:字节 –解码字符集utf-8–> String (读取数据,接收数据)

编码字符集和解码字符集不一致,就导致乱码的出现


文章作者: liuminkai
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 liuminkai !
评论
 上一篇
javase -- java常用类-StringBuilder和StringBuffer javase -- java常用类-StringBuilder和StringBuffer
StringBuilder和StringBuffer.1、String、StringBuilder、StringBuffer三者的异同?.不同 String:JDK1.0 不可变的字符序列 StringBuilder:JDK1.0 可变的字
2020-08-08
下一篇 
Spring学习笔记-14-声明式事务 Spring学习笔记-14-声明式事务
声明式事务.1、回顾事务. 事务在开发中十分重要,涉及到数据的一致性问题,不能马虎 确保完整性和一致性 把一组业务当成一个业务来做:要么都成功,要么都失败 事务ACID原则. 原子性 一致性 隔离性 多个业务可能操作同一个资源,防止数据损
2020-08-04
  目录