2020-10-24

String方法

equals:比较字符串是否相同
length:求字符串的长度
equalsIgnoreCase:忽略大小写后字符串是否相同
compareTo:根据字符串中每个字符的
Unicode编码进行比较
compareToIgnoreCase:根据字符串中每个字符的
Unicode编码进行忽略大小写比较
indexOf:目标字符或字符串在源字符串中位置下标
lastIndexOf:目标字符或字符串在源字符串中最后一次出现的位置下标valueOf:其他类型转字符串split:以某正则表达式分割字符串
substring:输出一个新的字符串,它是此字符串中的子串,形如substring(3,7);它将字符串中的第四个第五个第六个输出toLowerCase:将字符串中所有的大写改变成小写
toUpperCase:将字符串中所有的小写改变为大写
trim:去字符串首尾空格(将字符串开头的空白(空格)和尾部的空白去掉)
charAt:获取指定下标位置的字符
codePointAt:指定下标的字符的Unicode编码
concat:追加字符串到当前字符串
isEmpty:字符串长度是否为
0contains:是否包含目标字符串
startsWith:是否以目标字符串开头
endsWith:是否以目标字符串结束
format:格式化字符串
getBytes:获取字符串的字节数组
getChars:获取字符串的指定长度字符数组
toCharArray:获取字符串的字符数组join:以某字符串,连接某字符串数组matches:字符串是否匹配正则表达式
replace:将字符串中的某些字符用别的字符替换掉。形如replace(“abc”,”ddd”);字符串中的abc将会被ddd替换掉
replaceAll:带正则字符串替换replaceFirst:替换第一个出现的目标字符串

String类型(java.lang.String)
1.字符串的创建常量池: Java中的常量池,实际上分为两种形态:静态常量池和运行时常量池。
所谓静态常量池,即*.class文件中的常量池,class文件中的常量池不仅仅包含字符串,还包含类、方法的信息,占用class文件绝大部分空间。 而运行时常量池,则是JVM虚拟机在完成类装载操作后,将class文件中的常量池载入到内存中,并保存在方法区中,我们常说的常量池,就是指方法区中的运行时常量池。

 String a = "Hello World";

此种创建方式下,编译器首先检查常量池中是否含有此字符串常量,没有则创建,然后JVM会开辟一块堆内存存放一个隐式对象指向该字符串常量,接着在栈空间里创建a变量,a变量指向该块堆内存首地址。

 String a = new String("Hello World");

此种创建方式下,直接在堆内存new一个对象,并在常量池中创建“Hello World”字符串,该对象指向常量池中的“Hello World”字符串,然后创建a变量,并将a变量指向该块堆内存首地址。

2.字符串的特性

String是一个不可变的字符序列

String a1 = new String("Hello");
String a2 = new String("World");
a1 += a2;

此段代码执行时,首先在内存中分配一块空间,它的大小为a1和a2空间大小之和,然后将a1和a2的内容复制到该内存空间相应位置,最后将变量a1指向该内存空间。

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{
    /** The value is used for character storage. */
    private final char value[];

    /** The offset is the first index of the storage that is used. */
    private final int offset;

    /** The count is the number of characters in the String. */
    private final int count;

    /** Cache the hash code for the string */
    private int hash; // Default to 0

    ........
}

从String源码中分析可知,String类是final类,也即意味着String类不能被继承,并且它的成员方法都默认为final方法。在Java中,被final修饰的类是不允许被继承的,并且该类中的成员方法都默认为final方法。并且String类是通过char数组来存储字符串。

public String substring(int beginIndex, int endIndex) {
    if (beginIndex < 0) {
        throw new StringIndexOutOfBoundsException(beginIndex);
    }
    if (endIndex > count) {
        throw new StringIndexOutOfBoundsException(endIndex);
    }
    if (beginIndex > endIndex) {
        throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
    }
    return ((beginIndex == 0) && (endIndex == count)) ? this :
        new String(offset + beginIndex, endIndex - beginIndex, value);
}

分析String类中的substring方法可以发现,该方法的操作并不改变原有字符串的值,而是返回了一个新的字符串对象,这也与String类是一个不可改变的字符序列相吻合。

字符串的比较
“==”比较的是两个字符串地址是否相同,而.equals()方法比较的是两个字符串内容是否相同。
情况一:

String s1 = new String("java");
String s2 = new String("java");

System.out.println(s1==s2);            //false
System.out.println(s1.equals(s2));    //true

此段代码创建的是两个对象,他们有不同的堆空间,因此“==”为false;但内容相同,因此.equals()为true。

情况二:

String s1 = new String("java");
String s2 = s1;

System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));    //true

此段代码中变量s1,s2指向的为同一堆空间,并且字符串内容相同,因此均为true。

情况三:

String s1 = "java";
String s2 = "java";

System.out.println(s1==s2);            //true
System.out.println(s1.equals(s2));    //true

此段代码中,字符串创建方式为隐式创建,即,将String视为基本数据类型,因此,若字符串值相同,则s1,s2指向同一对象;若不同,则指向不同对象。

情况四:

 String s0="helloworld";
    String s1="helloworld";
    String s2="hello"+"world";
    System.out.println(s0==s1); //true 可以看出s0跟s1是指向同一个对象 
    System.out.println(s0==s2); //true 可以看出s0跟s2是指向同一个对象

此段代码中的s0和s1中的"helloworld”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true;而"hello”和"world”也都是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s2也同样在编译期就被解析为一个字符串常量,所以s2也是常量池中"helloworld”的一个引用。

情况五:

 String s0="helloworld"; 
    String s1=new String("helloworld"); 
    String s2="hello" + new String("world");
    s3="aaa";
    String s4=s0+s3;
    System.out.println( s0==s1 ); //false  
    System.out.println( s0==s2 ); //false 
    System.out.println( s1==s2 ); //false
    System.out.println( s4=="helloworldaaa" ); //false

用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。s0还是常量池中"helloworld”的引用,s1因为无法在编译期确定,所以是运行时创建的新对象"helloworld”的引用,s2因为有后半部分new String(”world”)所以也无法在编译期确定,所以也是一个新创建对象"helloworld”的引用。
String s4=s0+s3是运行时才可知的,而"helloworldaaa"是在编译时就存放在常量池中的。在之前说过,String的所有函数都是返回的一个新字符串而不改变原字符串,因此+运算符会在堆中建立来两个String对象,这两个对象的值分别是"helloworld"和"aaa",也就是说从字符串池中复制这两个值,接着在堆中创建两个对象,然后再在栈空间建立变量s4,将 "helloworldaaa"的堆地址赋给s4。

情况六:

  String s0 = "ab"; 
    final String s1 = "b"; 
    String s2 = "a" + s1;  
    System.out.println((s0 == s2)); // true

s1字符串加了final修饰,对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的"a" + s1和"a" + "b"效果是一样的。故上面程序的结果为true。

情况七:

 String s0 = "ab"; 
    final String s1 = getS1(); 
    String s2 = "a" + s1; 
    System.out.println("===========test10============");
    System.out.println((s0 == s2)); // false 

private static String getS1() {  
    return "b";   
}

这里虽然将s1用final修饰了,但是由于其赋值是通过方法调用返回的,那么它的值只能在运行期间确定,因此s0和s2指向的不是同一个对象,故上面程序的结果为false。
3.String、StringBuffer、StringBuilder的区别
(1)可变与不可变:String是不可变字符串对象,StringBuilder和StringBuffer是可变字符串对象(其内部的字符数组长度可变)。
(2)是否多线程安全:String中的对象是不可变的,也就可以理解为常量,显然线程安全。StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是StringBuffer 中的方法大都采用了synchronized 关键字进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是非线程安全的。
4.关于String str = new String(“abc”)创建了多少个对象? 这个问题在很多书籍上都有说到比如《Java程序员面试宝典》,包括很多国内大公司笔试面试题都会遇到,大部分网上流传的以及一些面试书籍上都说是2个对象,这种说法是片面的。 首先必须弄清楚创建对象的含义,创建是什么时候创建的?这段代码在运行期间会创建2个对象么?毫无疑问不可能,用javap -c反编译即可得到JVM执行的字节码内容:
很显然,new只调用了一次,也就是说只创建了一个对象。而这道题目让人混淆的地方就是这里,这段代码在运行期间确实只创建了一个对象,即在堆上创建了"abc"对象。而为什么大家都在说是2个对象呢,这里面要澄清一个概念,该段代码执行过程和类的加载过程是有区别的。在类加载的过程中,确实在运行时常量池中创建了一个"abc"对象,而在代码执行过程中确实只创建了一个String对象。
因此,这个问题如果换成 String str = new String(“abc”)涉及到几个String对象?合理的解释是2个。

5.常用方法
1.int length(); 返回字符串的长度
2.int indexOf(int ch); 返回该字符串第一个ch字符所在的位置
3.int indexOf(String str); 返回该字符串子字符串str起始位置
4.int lastIndexOf(int ch); 返回该字符串最后一个ch字符的位置
5.int lastIndexOf(String str); 返回该字符串最后一个str子字符串的起始位置
6.String substring(int beginIndex); 从字符串某个位置到结束截取字符串
7. String substring(int beginIndex, int endIndex); 从字符串的某个起始位置到结束(不包括末位置)截取字符串
8. 8.String trim(); 返回去除了前后空格的字符串
9.boolean equals( Obiect object ); 将自定字符串与指定对象比较
10.String toLowerCase(); 将字母转换成小写
11.String toUpperCase() 将字幕转换成大写
12.char charAt(int index); 获取字符串指定位子的字符
13 .String [] split(String regex ,int limit); 将字符串进行截取,返回子字符串数组
14.byte[] getBytes(); 将字符串转变为byte类型的数组

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值