• 神奇的瘦身利器让你轻松瘦身,放心变美

java byte转string乱码(byte数组转字符串java)

原创投稿 wpadmin 3年前 (2022-02-11) 231次浏览 0个评论

一、String基础

1、创建字符串方式

  1. String test = “abc”;
  2. String test = new String(“abc”);

2、String类是不可变的

java byte转string乱码(byte数组转字符串java)

  • String类被final关键字修饰,意味着String类不能被继承,并且它的成员方法都默认为final方法字符串一旦创建就不能再修改。
  • String实例的值是通过字符数组实现字符串存储的。

String类不可变的好处

  • 作为HashMap的键:因为String是不可变的,当创建String的时候哈希吗已经计算好了,所以每次在使用字符串的哈希码的时候就不用再计算一次,更高效
  • 线程安全:因为字符串是不可变的,所以一定是线程安全的,不用考虑多线程访问加锁的情况。
  • 字符串常量池的需要

3、String类常用方法

java byte转string乱码(byte数组转字符串java)

  • int indexOf(int ch, int fromIndex) / int indexOf(String str, int fromIndex):该字符串中查找从fromIndex开始第一次出现ch字符/str字符串的位置。

java byte转string乱码(byte数组转字符串java)

  • int lastIndexOf(int ch, int fromIndex) / int lastIndexOf(String str, int fromIndex):查找ch字符/str字符串在该字符串最后一次出现的位置。

java byte转string乱码(byte数组转字符串java)

  • String substring(int beginIndex, int endIndex):截取从beginIndex(包含)到endIndex(不包含)的字符串。

java byte转string乱码(byte数组转字符串java)

  • String trim():去除字符串中的前后空格

java byte转string乱码(byte数组转字符串java)

  • boolean equals(Object anObject):重写Object中的equals方法,字符串相同则返回true。

java byte转string乱码(byte数组转字符串java)

  • String toLowerCase():将字符串转换为小写。

java byte转string乱码(byte数组转字符串java)

  • String toUpperCase():将字符串转换为大写。

java byte转string乱码(byte数组转字符串java)

  • char charAt(int index):获取字符串中指定位置的字符。

java byte转string乱码(byte数组转字符串java)

  • String[] split(String regex, int limit):将字符串分割为子字符串,返回字符串数组

java byte转string乱码(byte数组转字符串java)

  • String replace(char oldChar, char newChar):把字符串序列中的oldChar替换为newChar。

java byte转string乱码(byte数组转字符串java)

  • byte[] getBytes():将该字符串转为byte数组

java byte转string乱码(byte数组转字符串java)

二、String高级

1、字符串常量池

字符串的分配和其他对象分配一样,是需要消耗高昂的时间和空间的,而且字符串使用的非常多。JVM为了提高性能和减少内存的开销,在实例化字符串的时候进行了一些优化:使用字符串常量池。每当创建字符串常量时,JVM会首先检查字符串常量池,如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。由于String字符串的不可变性,常量池中一定不存在两个相同的字符串。

字符串常量池在jdk1.7之前是存在方法去的,从1.7之后放到堆里面了。

2、String test = “abc”和new String(“abc”)区别

String test = “abc”:首先检查字符串常量池中是否存在此字符串,如果存在则直接返回字符串常量池中字符串的引用,如果不存在则添加此字符串进常量池然后返回此引用。

new String(“abc”):直接在堆中创建字符串返回新创建字符串的引用,每次创建都是一个新的对象。

如下例子:

java byte转string乱码(byte数组转字符串java)

3、intern()方法

直接使用双引号创建出来的String对象会直接存储在字符串常量池中,new创建的的String对象,可以使用String提供的intern方法。intern 方法是一个native方法,intern方法会从字符串常量池中查询当前字符串是否存在,如果存在,就直接返回当前字符串;如果不存在就会将当前字符串放入常量池中,之后再返回。

如下例子:

java byte转string乱码(byte数组转字符串java)

4、+字符串拼接

使用“+”拼接字符串时,JVM会隐式创建StringBuilder对象,每一个拼接就会隐式创建一个StringBuilder对象,当大量字符串拼接时,就会有大量StringBuilder在堆内存中创建,肯定会造成效率的损失,所以一般大量字符串拼接建议用StringBuilder(线程不安全)或StringBuffer(线程安全)。

如下例子看一下两者效率

java byte转string乱码(byte数组转字符串java)

运行输出:

java byte转string乱码(byte数组转字符串java)

从结果我们可以看到,10万次字符串的拼接用“+”的方式耗时13684毫秒,而StringBuilder拼接的话耗时1毫秒,效率是显而易见的。

当”+”两端均为编译期确定的字符串常量时,编译器会进行相应的优化,直接将两个字符串常量拼接好

看如下例子:

java byte转string乱码(byte数组转字符串java)

编译后class文件如下:

java byte转string乱码(byte数组转字符串java)

可见拼接的两个字符串如果是常亮则直接在编译器合并优化。

java byte转string乱码(byte数组转字符串java)

5、StringBuilder和StringBuffer拼接字符串

StringBuilder为了解决使用”+“大量拼接字符串时产生很多中间对象问题而提供的一个类,提供append和add方法,可以将字符串添加到已有序列的末尾或指定位置,实际上底层都是利用可修改的char数组(JDK 9 以后是 byte数组)来存储的,当前容量不足时触发扩容机制。

StringBuffer和StringBuilder的机制一样,唯一不同点是StringBuffer内部使用synchronized关键字来保证线程安全,保证线程安全不可避免的产生了一些额外的开销,如果不要求线程安全的情况下还是建议优先使用StringBuilder。

StringBuilder和StringBuffer都是继承AbstractStringBuilder抽象类,里面实现了字符串拼接的具体逻辑,我们来看一下:

java byte转string乱码(byte数组转字符串java)

数据都是保存在char[]里面,当容量不足时进行数组的扩容:

java byte转string乱码(byte数组转字符串java)

从源码可以看到,当需要容量不足时触发扩容机制,扩容为原来的2倍+2的容量,最大数组扩容容量为:MAX_ARRAY_SIZE = Integer.MAX_VALUE – 8,Integer.MAX_VALUE为2的31次方-1。扩容完后把老的数组里面的数据拷贝到新的数组里面。

6、String字符串长度限制

要回答这个问题要分两个阶段看,分别是编译期和运行期。不同的时期限制不一样。

编译期

我们所能想到的是String源码中定义,存储String字符的char数组最大是Integer.MAX_VALUE为2的31次方-1,那么也就是说可以存储2147483647个字符,分析到这时是不是以为大功告成了,其实不然,我们忽略了一点

我们编译java文件为class文件的时候是把字符串放在class的常量池中的,JVM对常量池的容量有严格的限制,JVN规定,字符串是由CONSTANTUtf8info类型的结构,CONSTANTUtf8_info的定义如下:

java byte转string乱码(byte数组转字符串java)

其中u1、u2是无符号的分别代表1个字节和2个字节,那么我们只需要看length最多允许两个字节的长度,因此理论上允许的的最大长度是2^16=65536。而 java class 文件是使用一种变体UTF-8格式来存放字符的,null 值使用两个 字节来表示,因此只剩下 65536- 2 = 65534个字节。

所以,在Java中,所有需要保存在常量池中的数据,长度最大不能超过65535,这当然也包括字符串的定义。

运行期

上面提到的这种String长度的限制是编译期的限制,也就是使用String str= “”;这种字面值方式定义的时候才会有的限制。

String在运行期的限制,其实就是我们前文提到的那个Integer.MAX_VALUE ,这个值约等于4G,在运行期,如果String的长度超过这个范围,就会抛出异常。


有肥胖困扰?专业瘦身老师教你1天瘦1斤

添加微信咨询:A-noweixin (手机长按可复制,加好友)

java byte转string乱码(byte数组转字符串java)
已帮助30000+人成功瘦身
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址