Java常用类-String

String

java.lang.Object
		java.lang.String
All Implemented Interfaces:
Serializable, CharSequence, Comparable<String>

String是个字符串常量类

public static void main(String[] args) {
        String str1 = new String("123");
        String str2 = new String("123");
        System.out.println(str1 == str2);
        System.out.println(str1.equals(str2));

        String str3 = "123";
        String str4 = "123";
        // str3 和 str4 指向同一块内存
        System.out.println(str3 == str4);
        System.out.println(str3.equals(str4));

        str3 = "234";
        str4 = "456";
        str4 = "789";
        String str5 = "456";
    }

String有自己的一块常量Pool,代码的内存模型如下:

在这里插入图片描述

常量Pool中的内存不会被垃圾回收,遇到大量叠加字符串的使用,如下:

public class TestString2 {
    public static void main(String[] args) {
        String str = "";
        // 以下循环会被分配100块内存,但只有最后一块内存被使用,
        // 而且String Pool中的内存不会被回收
        // 所以如果进行大量字符串叠加,不要使用以下方法
        for (int i = 0; i < 100; i++) {
            str+=i;
        }
        System.out.println(str);
    }
}

内存String Pool中会产生如下100块内存:

在这里插入图片描述

这种情况不要使用String来进行叠加,可以使用StringBuffer或StringBuilder

StringBuffer是线程安全的,StringBuilder是线程不安全的,但字符串一般不太考虑多线程,所以JDK5之后就引入了单线程的StringBuilder,用来更快处理字符串。

方法描述
public char charAt(int index)返回index对应的字符,index的范围是[0,length()-1],有越界异常判断
public int codePointAt(int index)返回index对应字符的Unicode码,index的范围是[0,length()-1],有越界异常判断
public int codePointBefore(int index)返回index对应字符前一位的Unicode码,index的范围是[1,length()],有越界异常判断
public int compareTo(String anotherString)按字典顺序比较两个字符串
此String对象按字典顺序位于参数字符串之前,结果是负整数。
此String对象按字典顺序位于参数字符串之后,结果是正整数
相同为0
public boolean contains(CharSequence s)String实现CharSequence接口,可以直接 s.contains("we")
public boolean contentEquals(CharSequence cs)String实现CharSequence接口,可以直接s.contentEquals("welcome")
public boolean contentEquals(StringBuffer sb)String s = new String("welcome");StringBuffer s2 = new StringBuffer("welcome"); System.out.println(s.contentEquals(s2)); 返回true
public static String copyValueOf(char[] data)valueOf(char[]) 一致
public static String join(CharSequence delimiter, CharSequence… elements)返回一个以delimiter为分隔,其他元素都join一起的字符串,注意:如果一个元素是null,那也会返回,delimiter为null,返回NullPointerException
public String[] split(String regex)字符串切割成字符串数组
split(“.”)改成split(“\.”)
public String toLowerCase()小写字母转换
public boolean matches(String regex)字符串是否匹配正则表达式
public CharSequence subSequence(int beginIndex, int endIndex)截取字符串的下标范围[beginIndex,endIndex]
public char[] toCharArray()转换字符串为字符数组
public static String valueOf(boolean b)valueOf()方法有很多参数可以参考
intern()

尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作。在调用”ab”.intern()方法的时候会返回”ab”,但是这个方法会首先检查字符串池中是否有”ab”这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然会返回这个字符串的引用。

可以看下面一个范例:

String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = str1 + str2;
String str5 = new String("ab");
 
System.out.println(str5.equals(str3));
System.out.println(str5 == str3);
System.out.println(str5.intern() == str3);
System.out.println(str5.intern() == str4);

输出:
true
false
true
false

为什么会得到这样的一个结果呢?我们一步一步的分析。

  • str5.equals(str3)这个结果为true,不用太多的解释,因为字符串的值的内容相同。

  • str5 == str3对比的是引用的地址是否相同,由于str5采用new String方式定义的,所以地址引用一定不相等。所以结果为false。

  • 当str5调用intern的时候,会检查字符串池中是否含有该字符串。由于之前定义的str3已经进入字符串池中,所以会得到相同的引用。

  • 当str4 = str1 + str2后,str4的值也为”ab”,但是为什么这个结果会是false呢?(这是因为str4是由两个变量连接的,含有变量的连接是不会进入字符串池的)先看下面代码:

    String a = new String("ab");
    String b = new String("ab");
    String c = "ab";
    String d = "a" + "b";
    String e = "b";
    String f = "a" + e;
    
    System.out.println(b.intern() == a);
    System.out.println(b.intern() == c);
    System.out.println(b.intern() == d);
    System.out.println(b.intern() == f);
    System.out.println(b.intern() == a.intern());
    
    输出:
    false
    true
    true
    false
    true
    

由运行结果可以看出来,b.intern() == a和b.intern() == c可知,采用new 创建的字符串对象不进入字符串池,并且通过b.intern() == d和b.intern() == f可知,字符串相加的时候,都是静态字符串的结果会添加到字符串池,如果其中含有变量(如f中的e)则不会进入字符串池中。但是字符串一旦进入字符串池中,就会先查找池中有无此对象。如果有此对象,则让对象引用指向此对象。如果无此对象,则先创建此对象,再让对象引用指向此对象。

当研究到这个地方的时候,突然想起来经常遇到的一个比较经典的Java问题,就是对比equal和==的区别,当时记得老师只是说==判断的是“地址”,但是并没说清楚什么时候会有地址相等的情况。现在看来,在定义变量的时候赋值,如果赋值的是静态的字符串,就会执行进入字符串池的操作,如果池中含有该字符串,则返回引用。

执行下面的代码:

String a = "abc";
String b = "abc";
String c = "a" + "b" + "c";
String d = "a" + "bc";
String e = "ab" + "c";
        
System.out.println(a == b);
System.out.println(a == c);
System.out.println(a == d);
System.out.println(a == e);
System.out.println(c == d);
System.out.println(c == e);

输出:
true
true
true
true
true
true

总结:
1.采用new 创建的字符串对象不进入字符串池

2.字符串相加的时候,都是静态字符串的结果会添加到字符串池

3.如果其中含有变量,则不会进入字符串池中

split()

split使用regex匹配,需要注意特殊符号的转义:

public static void main(String[] args) {
    String str = "hello|world|how|are|you.thanks.and you.*i*am*fun\\what\\";
    String[] split = str.split("\\|");
    for (String s : split) {
        System.out.println(s);
    }
    System.out.println("---------------.-----------------");
    split = str.split("\\.");
    for (String s : split) {
        System.out.println(s);
    }
    System.out.println("----------------*----------------");
    split = str.split("\\*");
    for (String s : split) {
        System.out.println(s);
    }
    System.out.println("-----------------\\\\---------------");
    split = str.split("\\\\");
    for (String s : split) {
        System.out.println(s);
    }

}
substring()
substring(int beginIndex, int endIndex)

返回一个指针下标以 beginIndex开始,扩展到endIndex-1的字符串

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值