String的特性和String,StringBuffer,StringBuilder的对比

Posted 小布丁value

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了String的特性和String,StringBuffer,StringBuilder的对比相关的知识,希望对你有一定的参考价值。

1.源码实现(笔试)

  • Sting是一个final类,不能被继承
  • String 实现了Serializable接口:表示字符串是支持序列化的,实现了Comparable 接口,表示String 可以比大小。
  • String 内部定义了final char value[] 数组 用来存储数组,
  • String具有不可变性
    体现:1.当对字符串你重新赋值时,需要重写指定内存区域赋值,不能用原有的value进行赋值 2.对现有字符串进行拼接时,也需要重新指定内存区域赋值,不能用原有的value进行赋值
    3.String的replace()方法修改字符或字符串时,需要重新指定内存区域
  • 通过字面量的方式(区别于new)给一个字符串赋值,此时字符 串值声明在字符串常量池中。
  • 字符串常量池是不会存储相同内容的字符串的。
  • 通过new 对象 的方式在 堆上和常量池个保存一份
public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    private int hash; // Default to 0

通过jvm说明一下通过字面量的方式命名和通过new 对象的方式说明(懂得可以跳过)

字面量方式命名

new对象创建

public String() {
       // this.value = "".value;
    }
    public String(String original) {
        //this.value = original.value;
        //this.hash = original.hash;
    }
    public String(char value[]) {
        //this.value = Arrays.copyOf(value, value.length);
    }
    public String(char value[], int startindex, int count) {

区别

  • 字符串常量存储在字符串常量池,目的是共享
  • new 对象 在堆上存储,字符串常量堆和常量池各一分

练习


题目二:

Person p1 = new Person();
p1.name = "atguigu";
Person p2 = new Person();
p2.name = "atguigu";
System.out.println(p1.name .equals( p2.name)); //true String类重写了equals方法
System.out.println(p1.name == p2.name); //true 都在常量池
System.out.println(p1.name == "atguigu"); 
// true  常量池不会存储相同字符串
String s1 = new String("bcde");
String s2 = new String("bcde");
System.out.println(s1==s2);//fasle 堆上地址不同


题目三:判断题

  • 结论:
  • 常量与常量的拼接结果在常量池。且常量池中不会存在相同内容的常量。
  • 只要其中有一个是变量,结果就在堆中
  • 如果拼接的结果调用intern()方法,返回值就在常量池中

题目四

经典面试题

public class StringTest {
String str = new String("good");
char[] ch = { 't', 'e', 's', 't' };
public void change(String str, char ch[]) {
str = "test ok";
ch[0] = 'b'; }
public static void main(String[] args) {
StringTest ex = new StringTest();
ex.change(ex.str, ex.ch);
System.out.print(ex.str );// good
System.out.println(ex.ch);//best
} }

说明: str作用在 change函数中,与外面的的str没有任何关系,所以它无论怎么变。外面的str都不会变
但数组穿的是地址,值是可以变的
此处类似于c语言的解引用

2.常用方法(机试)

常用方法1:

-int length();返回字符串的长度

  • char charAt(int index) 返回索引处字符
  • boolean isEmpty() 判断是否是空字符串
  • String toLowerCase() 使用默认语言环境,将String中所有的字符串转换为小写
  • String toUpperCase() 使用默认语言环境,将String 中的所有字符串转换为大写
  • String trim(); 去掉头部和尾部的空字符串
  • boolean equals(Object obj):比较字符串的内容是否相同
  • boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大
    小写
  • String concat(String str):拼接=“+”
  • int compareTo(String anotherString):比较两个字符串的大小
  • String substring(int beginIndex):beginIndex开始截取到最后的一个子字符串。
  • String substring(int beginIndex, int endIndex)
    符串从beginIndex开始截取到endIndex。
    注意 左开右闭

常用方法二:

  • boolean endsWith(String suffix): 测试字符串是否以指定的后缀结束
  • boolean startsWith(String prefix):测试字符串是否以指定的前缀结束
  • boolean startsWith(String prefix,int toffset):测试 是否从开始到结束-1;
  • boolean contains(CharSequence s) 当且仅当此字符串包含指定的char值序列时,返回true;
  • int indexOf(String str)返回指定子字符串再次字符串中第一次出现出的索引
  • int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出
    现处的索引,从指定的索引开始
  • int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
  • int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后
    一次出现处的索引,从指定的索引开始反向搜索
    注:indexOf和lastIndexOf方法如果未找到都是返回-1
    常用方法三:
  • String replace(char oldChar,char newChar): new 替换掉所用的old
  • String replace(CharSequence target, CharSequence replacement):使
    用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
  • String replaceAll(String regex,String replacement) 使用给定的replacement替换
    此字符串所有匹配给定的正则表达式的子字符串
  • String replaceFist(String segex,String replacement)使用给定的正则表达式替换此字符串匹配给定正则表达式的第一个子字符串
  • boolean matches(String regex);告知此字符串是否匹配给定的正则表达式
  • String []split(String regex):根据给定的正则表达式的匹配拆分此字符串
  • String[] split(String regex,int limit)根据给定的正则表达式来拆分字符串,最多不超过limit个,如果超过了,剩下的全部放到最后一个元素中

Stirng与基本 数据类型之间的转换

1.String 转换为基本数据类型

  • Integer包装类的public static int parseInt(String s):可以将由“数字”字符组成的字符串转换为整型。
  • 类似地,使用java.lang包中的Byte、Short、Long、Float、Double类调相应 的类方法可以将由“数字”字符组成的字符串,转化为相应的基本数据类型。
    1.基本数据类型转换成String
    调用String类的public String valueOf(int n)可将int型转换为字符串
    相应的valueOf(byte b)、valueOf(long l)、valueOf(float f)、valueOf(double
    d)、valueOf(boolean b)可由参数的相应类型到字符串的转换
public class calssd {
    public static void main(String[] args) {
        String str = "123";
        int a = 34532;
        int num = Integer.parseInt(str);//数字组成的字符串转化为基本数据类型
        System.out.println(getType(a));//int 
        String b = String.valueOf(a);//基本数据类型包装成字符串
        System.out.println(getType(b));//class java.lang.String
    }
    public static  String getType ( int o){
        return "int";
    }
    public   static String getType(Object o){
        return o.getClass().toString();
    }
}

Sting 与字符数组转换

1.字符数组->字符串
String 类的构造器:
String(char[])
String(char[],int statindex,int length)
字符数组转字符串
2.字符串->字符数组
public char[] toCharArray()
public void getChars(int srcBegin,int srcEnd,char[] dst,int dstBegin)

 public static void main(String[] args) {
        String str = "123";
        char [] a=str.toCharArray();
        System.out.println(Arrays.toString(a));
        char[] b={'v','r'};
        String c = new String(b);
        System.out.println(c);
    }

String与字节数组转换

1.字节数组->字符串
String构造函数

  • String(byte[]) 通过使用平台的默认字符集解码指定byte数组,构造一个新的String
  • String(byte[],int startindex,int length)

2.字符串->字节数组
public byte[] getBytes() 使用平台的默认字符集将此String编码转变为byte序列,并将结果存储到一个新的byte数组中
public byte[] getBytes(String charsetName)
指定的转化为byte数组

public static void main(String[] args) throws UnsupportedEncodingException {
       String str="abcde";
       char[] chars=str.toCharArray();

       //byte [] bytes = str.getBytes("UTF-8");//默认是,
        byte [] bytes = str.getBytes();
       for(int i=0;i<bytes.length;i++){
           System.out.print(bytes[i]+" ");
       }
        System.out.println();
     String s=  new String(bytes);
        System.out.println(s);
    }

3.String,StringBuffer和StringBuilder的区别

(从三个点去谈:1,可不可变,底层实现
2.线程安全
3.效率对比StringBuilder>StringBuffer>String

  • String 不可变的序列:
    底层用 final char [] value 存储

  • StringBuffer 可变的字符序列 用char[] value存储,可以对字符内容进行增删,此时不会产生新的对象,线程安全
    StringBuffer su=new StringBuffer();//char []
    value = new char[16];底层创建了长度为16的数组。

    StringBuffer s= new StringBuffer(“abc”) 底层创建了''abc''.length()+16的数组//s
    思考一下:StringBuffer s=new StringBuffer(a.length); 长度是多少呢//3因为count记录有效数据的个数
    扩容是<<1+2扩容

  • StringBuilder可变的字符串序列 底层用 char[]
    线程不安全,效率高


线程安全

在这里插入图片描述

  • StringBuffer类不同于String,对象必须用构造器生成
public StringBuffer() {
        super(16);
    }

public StringBuffer(String str) {
        super(str.length() + 16);
        append(str);
    }

StringBuffer的常用方法


扩容方式

 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
 private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
    }

以上是关于String的特性和String,StringBuffer,StringBuilder的对比的主要内容,如果未能解决你的问题,请参考以下文章

String StringBuffer StringBuilder

string stringbuffer StringBuilder

String Buffer和StringBuilder类-java

字符串String

字符串String

java:String