String类详解

本文详细介绍了Java中String对象的构造方法,字符串的创建方式、引用机制,以及字符串操作的优化,包括+运算符的优化、常用方法如charAt、indexOf等,还讨论了StringBuilder和StringBuffer的异同。
摘要由CSDN通过智能技术生成

String的构造方法

String(): 创建内容为空的字符串对象

String(byte[] bytes):将指定的字节数组转换为字符串对象

String(char[] chars):将指定的字符数组转换为字符串对象

String(String str):创建指定内容的字符串对象

public class Demo1 {
    public static void main(String[] args) {
        /*
        使用构造方法创建字符串对象
         */
        //创建空的字符串
        String str = new String();
        System.out.println(str.hashCode());
        //修改字符串的值
        str += "haha";
        //打印字符串对象的hashCode值,根据打印结果我们猜测,String应该是重写了hashCode方法
        System.out.println(str.hashCode());
        System.out.println(str);

        //创建指定内容的字符串对象
        String str2 = new String("hello");
        System.out.println(str2);


        //将指定的字节数组转换为字符串
        byte[] bytes = {97,98,99,100};
        String str3 = new String(bytes);
        System.out.println(str3);

        //将指定的字符数组转换为字符串
        char[] chars = {'我','爱','学','习'};
        String str4 = new String(chars);
        System.out.println(str4);


        /*
        直接使用字面量创建字符串对象
         */
        String str5 = "helloworld";
        System.out.println(str5);
    }
}

两种创建字符串对象的方式的区别

 

根据这幅图可得:

如果用字面量的方式,最多只会在常量池创建一个对象

如果使用构造方法的方式,最少会在堆中单独创建一个String对象

那么:创建的String对象是通过什么属性来引用的字符串呢

通过查看String类的源码:找到了该变量

private final char value[];

说明了字符串的底层就是一个字符数组

字符串对+的优化

public class Demo3 {
    public static void main(String[] args) {
        /*
        创建了多少个对象
         */
        String s1 = "hello";
        String s2 = "world";
        //当+左右两边都是字面量时,java会将+直接优化掉
        String s4 = "hello" + "world";
    }
}

常见方法-获取字符串信息

char charAt(int index):获取指定索引处的字符

int indexOf(char ch):获取指定字符串在字符串中第一次出现的索引 如果没有该字符,返回-1

int indexOf(char ch,int fromIndex):从指定索引处开始查询指定的字符串第一次出现的索引

int lastIndexOf(char ch):查询指定的字符在字符串中最后出现的索引 如果没有该字符,返回-1

int hashCode():获取当前对象的hashCode值

int length():获取字符串的长度

public class Demo4 {
    public static void main(String[] args) {
        String str = "hell o ";
        //charAt方法
        System.out.println(str.charAt(3));//l
        //length方法
        System.out.println(str.length());//5
        //遍历字符串中的每一个字符
        for (int i = 0; i < str.length(); i++) {
            System.out.print(str.charAt(i) + " ");
        }
        System.out.println();

        //indexOf方法
        System.out.println(str.indexOf('l'));//2
        System.out.println(str.lastIndexOf('l'));//3
        System.out.println(str.indexOf('l',3));//3

        //hashCode方法
        /*
        String类重写了hashCode方法
        该方法的返回值与字符串的内容相关
        几乎可以认为:内容相同的字符串的的hashCode值相等
         */
        System.out.println(str.hashCode());
    }
}

String判断相关的方法

boolean contains(String str):判断当前字符串中是否包含指定字符串

boolean endsWith(String str):判断当前字符串的内容是否以指定内容结尾

boolean startsWith(String str):判断当前字符串的内容是否以指定内容开头

boolean equals(String str):判断当前字符串与指定字符串的内容是否一致

boolean equalsIgnoreCase(String str):判断当前字符串与指定字符串的内容在忽略大小写时是否一致

boolean isEmpty():判断是否是空字符串
 

举例说明:


public class Demo1 {
    public static void main(String[] args) {
        String str = "helloworld";
        System.out.println(str.contains("w"));//true
        System.out.println(str.endsWith("world"));//true
        System.out.println(str.startsWith("he"));//true
        String str1 = new String("hello");
        String str2 = new String("hello");
        String str3 = new String("HeLLo");

        System.out.println(str1 == str2);//false
        System.out.println(str1.equals(str2));//true
        System.out.println(str1.equals(str3));//false
        System.out.println(str1.equalsIgnoreCase(str3));//true

        String str4 = "";
        System.out.println(str4.isEmpty());
    }
}

String修改值的相关方法

String replace(String oldStr, String newStr):将当前字符串中的oldStr子串替换为指定的newStr

String subString(int index):从当前字符串的index索引处到最后截取子串

String subString(int beginIndex, int endIndex):从当前字符串索引为beginIndex到endIndex-1 处,截取子串

String toUpperCase():将当前字符串的内容全部转换为大写

String toLowerCase():将当前字符串的内容全部转换为小写

注意:String的值是不能修改的。所以上面的每一个方法其实都是新建了一个String对象作为返回值,调用该方法的String的内容是没有改变的。

转换相关的方法

/String replace(String oldStr, String newStr):将当前字符串中的oldStr子串替换为指定的newStr
String subString(int index):从当前字符串的index索引处到最后截取子串
String subString(int beginIndex, int endIndex):从当前字符串索引为beginIndex到endIndex-1 处,截取子串
    注意:取前不取后     截取到endIndex-1索引处
String toUpperCase():将当前字符串的内容全部转换为大写
String toLowerCase():将当前字符串的内容全部转换为小写


public class Demo2 {
    public static void main(String[] args) {
        String str = "I hate study hahahaha";
        //将str中hate改为love
        str = str.replace("hate", "love");//注意一定要接收返回值
        System.out.println(str);

        //截取str中最后的hahahaha
        int index = str.indexOf("hahahaha");//获取hahahaha 在str中第一次出现的索引
        str = str.substring(index);
        System.out.println(str);

        str = "I hate study hahahaha";
        //截取str中的study
        index = str.indexOf("s");
        str = str.substring(index, index + 6);
        System.out.println(str);

        str = "I hate study hahahaha";
        //将str内容全部转换为大写
        str = str.toUpperCase();
        System.out.println(str);
        //将str内容全部转换为小写
        str = str.toLowerCase();
        System.out.println(str);
    }
}

字符串和字符数组之间的转换

static String valueOf(几乎可以是所有的其他类型):将指定的参数转换为字符串

byte[] getBytes():将当前字符串转换为字节数组

char[] toCharArray():将当前字符串转换为字符数组

new String(byte[] bytes):将指定的字节数组转换为字符串

new String(char[] chars):将指定的字符数组转换为字符串

public class Demo3 {
    public static void main(String[] args) {
        boolean boo = false;
        String str = String.valueOf(boo);
        System.out.println(str);

        String s = "你好世界haha";
        //将s转换为字符数组
        char[] chars = s.toCharArray();
        System.out.println(Arrays.toString(chars));
        //将该字符数组转换回字符串
        s = String.valueOf(chars);
        System.out.println(s);

        String s2 = "hello世界";
        //将s2转换为字节数组
        byte[] bytes = s2.getBytes();
        System.out.println(Arrays.toString(bytes));
        //将该字节数组转换回字符串
        s2 = new String(bytes);
        System.out.println(s2);
    }
}

StringBuilder 与 StringBuffer

这两个类的功能几乎是一致的,但是StringBuffer是线程安全的

多个线程访问一个方法:

有可能出现a线程在操作某个属性值的时候  b线程也来操作这个属性值

这种情况就可能会发生线程安全问题

具体的例子:

卖票:

a窗口     b窗口   

如果总共只剩一张票,但是有两个客户同时去a/b窗口买票,可能会出现两个客户都买到票

这就是线程安全问题

如何解决线程安全问题:排队

如果一个类是线程安全的,说明如果有多个线程访问它的方法,需要排队,所以效率较低

如果一个类不是线程安全的,说明多个线程可以同时访问它的方法,效率提高,但是有安全问题

StringBuilder

是一个可变的字符串:这个字符串的内容是可以修改的。

new StringBuilder():创建一个内容为空的可变字符串

new StringBuilder(String str):创建一个指定内容的可变字符串

如果要经常修改字符串的值,我们建议不要使用String

因为如果使用String,则每修改一次就会创建一个新的String的对象,浪费内存空间

这种情况建议使用StringBuilder....

常用方法

append(几乎所有的类型):将指定的数据添加到当前字符串的末尾

insert(int index, 任意类型的数据):将指定数据添加到当前字符串的指定位置

delete(int start, int end):删除指定范围索引之间的子串

deleteCharAt(int index):删除指定索引处的字符

reverse():将内容反转   

toString():将当前可变字符串转换为String类型

public class Demo2 {
    public static void main(String[] args) {
        String str = "我爱世界";
        StringBuilder sb = new StringBuilder(str);
        //向字符串的末尾添加内容  因为StringBuilder是可变字符串
        //所以本质上就是修改了自己的内容   不需要去接收
        sb.append(666);
        System.out.println(sb);
        //在我 与 爱之间添加  "very"
        sb.insert(1, "very");
        System.out.println(sb);
        //删除最后的 666
        sb.delete(8,11);
        System.out.println(sb);
        //将内容反转
        sb.reverse();
        System.out.println(sb);

        /*
        实际开发中大多数情况需要的字符串都是String
        但是如果要对内容进行频繁的修改建议将String先转换成StringBuilder进行操作
        操作完成之后再转换回String
         */
        str = sb.toString();
        System.out.println(str);
    }
}
  • 8
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值