String类详解

一、String的基本认识

1、String的两种实例化方式

第一种方式较为常用,是直接赋值的方法,如下面的代码,但String本身是一个类,类存在构造方法,所以String还可以通过构造方法实例化。

//第一种方式,直接赋值
String str1 = "Hello";

//第二种方式,通过构造方法
String str2 = new String("Hello!");

实例化好的对象str1,str2存放在栈中,是引用(相当于C语言中的地址)。而“Hello”,“Hello!”则存放在堆中

两种实例化对象的区别:

1、直接赋值

String str1 = "Java is best";
String str2 = "Java is best";
String str3 = "Java is best";

String类的设计使用了共享的设计模式   只适用于直接赋值法!!!

在JVM底层实际上会自动维护一个对象池(字符串对象池),如果采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)会直接保存到这个对象池中。如果下次继续使用直接赋值的方式声明String对象,则会优先查看对象池,如果有指定内容,将直接进行引用;如果没有,则开辟新的字符串对象,并将其保存在对象池值中,并供下次使用。如下图所示。

这样可以节省大量的空间!对象池其实就是一个对象数组。

用直接赋值法创建第一个对象str1时,对象池中什么也没有,所以在对象池中添加“Java is best”,用直接赋值法创建第二个对象str2时,查看对象池,对象池中有“Java is best”,将直接进行引用(如果没有,则开辟新的字符串对象,并将其保存在对象池值中,并供下次使用);用直接赋值法创建第三个对象str3时,查看对象池,对象池中有“Java is best”,将直接进行引用。

2、采用构造方法实例化

String str4 = new String("Java is best");

刚开始时"Java is best"是一个匿名对象,如下图所示

new String()时会在堆上开辟空间存放"Java is best",并且将str4指向它,刚刚的匿名对象就会被抛弃了,成为垃圾对象(栈上没有地址指向的对象),等待垃圾回收器的回收。如下图

所以通过构造方法实例化,会造成大量的垃圾空间,它会开辟两个空间,其中一个是匿名对象,实例完成后成为垃圾空间,另一个是真正的对象。

既然通过构造方法是浪费空间的,那有没有方法改变这个?  有的!  那就是String对象入池操作

//将str入池--->共享
String str = new String("Hello").intern();

查看Sting的API

会发现

1、String在java.lang包底下(这个包是自动导入的)

2、通过

public final class String  extends Object  implements Serializable, Comparable<String>, CharSequence  

知道String是Object的子类且不可被继承

2、String的构造方法

可以通过以下任意一个构造方法来创建String对象,标明为已弃用的最好就不要用了,因为它在版本升级过程中,未来版本有可能就不支持了

3、字符串比较

public class Strings1{
	public static void main(String[] args){
		int x = 10;
		int y = 10;
		System.out.println(x==y);//true
		
		String str1 = "Java is best";
		String str2 = "Java is best";
		String str3 = new String("Java is best");
		System.out.println(str1==str2);//true
		System.out.println(str1==str3);//false
	}
}

上述代码中的变量,在内存中的情况如下图所示:(具体是为什么,在字符串入池时讲过啦,见两种实例化对象的区别)

至于为什么为会出现这样的结果,是因为代码中的“==”比较的值是栈空间的值

对于基本数据类型来说,他们的值本身就存放在栈空间,

而对于引用数据类型来说,他们真正的值存放在堆空间,对象的引用(可以看成地址)存放在栈空间。所以“==”比较的是他们的地址的值,也就是看他们是否是同一个对象,而非String的内容

如果要比较String的内容,可以用equals()这个方法!在String中equals方法比较的是字符串内容。

其实在Java中所有的类都继承自Object类,而equals就是Object中的方法,这个方法本质上就是“==”,比较对象是否是一个对象。哪为什么在String中equals不这么用呢?是因为String类覆写了Object的方法。

public class Strings1{
	public static void main(String[] args){
		
		String str1 = "Hello";
		String str3 = new String("Hello");
		System.out.println(str1.equals(str3));//true
	}
}
//这是Object的equals() 的源代码   本质上是==
public boolean equals(Object obj) {
        return (this == obj);
 }

//这是String的equals()的源代码
public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

小技巧:在字符串的值与匿名的字符串equals()比较时,可以将匿名字符串放在前面,因为匿名字符串不可能为空,即不可能出现“NullPointerException”问题

	String str4 = null;
        System.out.println("Hello".equals(str4));//false
	System.out.println(str4.equals("Hello"));//NullPointerException

4、字符串不可变

字符串一旦定义就不能改变!------>一旦改变就会产生新的字符串对象

因为Java语言对于字符串的底层实现是字符数组,数组的缺陷是长度固定,所以在字符串定义常量时,他的内容不可改变。

就像下面的代码一样,一共创建出了5个对象,显然这样写代码是不好的。如果对字符串有大量的改变,java中提供了两个类:StringBuffer和StringBuilder可以解决这个问题。

public static void main(String[] args){	
	String str1 = "Hello";
	str1 = str1+" world";
	str1 += "!!!";
	System.out.println(str1);//"Hello world!!!"
}

执行完String str1 = "Hello";后,内存分派如下图:


    执行完str1 = str1+" world";后,内存分派如下图:

注意:垃圾对象不在对象池中,如果给匿名对象赋值了,才会将匿名对象放在池子中。因为如果将每一个匿名对象都放在池子中,池子将会很快被填满,而且匿名对象因为没有引用,所以只能用一次,放在池子中时没有意义的,只是占用了空间。


    执行完str1 += "!!!";后,内存分派如下图:

当然了,如果你写了这样一个代码:String str = "Hello"+" World"+"!!!";

Java在编译成字节码时会优化为这样String str = "Hello World!!!";并且将它放在池子中。

二、关于String的方法

查看String的API

    • Modifier and TypeMethod and Description
      charcharAt(int index)

      返回 char指定索引处的值。

      intcodePointAt(int index)

      返回指定索引处的字符(Unicode代码点)。

      intcodePointBefore(int index)

      返回指定索引之前的字符(Unicode代码点)。

      intcodePointCount(int beginIndex, int endIndex)

      返回此 String指定文本范围内的Unicode代码点数。

      intcompareTo(String anotherString)

      按字典顺序比较两个字符串。

      intcompareToIgnoreCase(String str)

      按字典顺序比较两个字符串,忽略病例差异。

      Stringconcat(String str)

      将指定的字符串连接到该字符串的末尾。

      booleancontains(CharSequence s)

      当且仅当此字符串包含指定的char值序列时才返回true。

      booleancontentEquals(CharSequence cs)

      将此字符串与指定的CharSequence进行 CharSequence

      booleancontentEquals(StringBuffer sb)

      将此字符串与指定的StringBuffer进行 StringBuffer

      static StringcopyValueOf(char[] data)

      相当于 valueOf(char[])

      static StringcopyValueOf(char[] data, int offset, int count)

      相当于 valueOf(char[], int, int)

      booleanendsWith(String suffix)

      测试此字符串是否以指定的后缀结尾。

      booleanequals(Object anObject)

      将此字符串与指定对象进行比较。

      booleanequalsIgnoreCase(String anotherString)

      将此 String与其他 String比较,忽略案例注意事项。

      static Stringformat(Locale l, String format, Object... args)

      使用指定的区域设置,格式字符串和参数返回格式化的字符串。

      static Stringformat(String format, Object... args)

      使用指定的格式字符串和参数返回格式化的字符串。

      byte[]getBytes()

      使用平台的默认字符集将此 String编码为字节序列,将结果存储到新的字节数组中。

      byte[]getBytes(Charset charset)

      使用给定的charset将该String编码为字节序列,将结果存储到新的字节数组中。

      voidgetBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin)已弃用

      此方法无法将字符正确转换为字节。 从JDK 1.1开始,首选的方法是通过getBytes()方法,该方法使用平台的默认字符集。

      byte[]getBytes(String charsetName)

      使用命名的字符集将此 String编码为字节序列,将结果存储到新的字节数组中。

      voidgetChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)

      将此字符串中的字符复制到目标字符数组中。

      inthashCode()

      返回此字符串的哈希码。

      intindexOf(int ch)

      返回指定字符第一次出现的字符串内的索引。

      intindexOf(int ch, int fromIndex)

      返回指定字符第一次出现的字符串内的索引,以指定的索引开始搜索。

      intindexOf(String str)

      返回指定子字符串第一次出现的字符串内的索引。

      intindexOf(String str, int fromIndex)

      返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。

      Stringintern()

      返回字符串对象的规范表示。

      booleanisEmpty()

      返回 true如果,且仅当 length()0

      static Stringjoin(CharSequence delimiter, CharSequence... elements)

      返回一个新的字符串,由 CharSequence elements的副本组成,并附有指定的delimiter的 delimiter

      static Stringjoin(CharSequence delimiter, Iterable<? extends CharSequence> elements)

      返回一个新 String的副本组成 CharSequence elements与指定的副本一起加入 delimiter

      intlastIndexOf(int ch)

      返回指定字符的最后一次出现的字符串中的索引。

      intlastIndexOf(int ch, int fromIndex)

      返回指定字符的最后一次出现的字符串中的索引,从指定的索引开始向后搜索。

      intlastIndexOf(String str)

      返回指定子字符串最后一次出现的字符串中的索引。

      intlastIndexOf(String str, int fromIndex)

      返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。

      intlength()

      返回此字符串的长度。

      booleanmatches(String regex)

      告诉这个字符串是否匹配给定的 regular expression

      intoffsetByCodePoints(int index, int codePointOffset)

      返回此 String内的指数,与 index codePointOffset代码点。

      booleanregionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)

      测试两个字符串区域是否相等。

      booleanregionMatches(int toffset, String other, int ooffset, int len)

      测试两个字符串区域是否相等。

      Stringreplace(char oldChar, char newChar)

      返回从替换所有出现的导致一个字符串 oldChar在此字符串 newChar

      Stringreplace(CharSequence target, CharSequence replacement)

      将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列。

      StringreplaceAll(String regex, String replacement)

      用给定的替换替换与给定的 regular expression匹配的此字符串的每个子字符串。

      StringreplaceFirst(String regex, String replacement)

      用给定的替换替换与给定的 regular expression匹配的此字符串的第一个子字符串。

      String[]split(String regex)

      将此字符串分割为给定的 regular expression的匹配。

      String[]split(String regex, int limit)

      将这个字符串拆分为给定的 regular expression的匹配。

      booleanstartsWith(String prefix)

      测试此字符串是否以指定的前缀开头。

      booleanstartsWith(String prefix, int toffset)

      测试在指定索引处开始的此字符串的子字符串是否以指定的前缀开头。

      CharSequencesubSequence(int beginIndex, int endIndex)

      返回一个字符序列,该序列是该序列的子序列。

      Stringsubstring(int beginIndex)

      返回一个字符串,该字符串是此字符串的子字符串。

      Stringsubstring(int beginIndex, int endIndex)

      返回一个字符串,该字符串是此字符串的子字符串。

      char[]toCharArray()

      将此字符串转换为新的字符数组。

      StringtoLowerCase()

      将所有在此字符 String使用默认语言环境的规则,以小写。

      StringtoLowerCase(Locale locale)

      将所有在此字符 String ,以降低使用给定的规则情况下 Locale

      StringtoString()

      此对象(已经是字符串!)本身已被返回。

      StringtoUpperCase()

      将所有在此字符 String使用默认语言环境的规则大写。

      StringtoUpperCase(Locale locale)

      将所有在此字符 String使用给定的规则,大写 Locale

      Stringtrim()

      返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。

      static StringvalueOf(boolean b)

      返回 boolean参数的字符串 boolean形式。

      static StringvalueOf(char c)

      返回 char参数的字符串 char形式。

      static StringvalueOf(char[] data)

      返回 char数组参数的字符串 char形式。

      static StringvalueOf(char[] data, int offset, int count)

      返回 char数组参数的特定子阵列的字符串 char形式。

      static StringvalueOf(double d)

      返回 double参数的字符串 double形式。

      static StringvalueOf(float f)

      返回 float参数的字符串 float形式。

      static StringvalueOf(int i)

      返回 int参数的字符串 int形式。

      static StringvalueOf(long l)

      返回 long参数的字符串 long形式。

      static StringvalueOf(Object obj)

      返回 Object参数的字符串 Object形式。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值