字符串表示一个字符序列。在Java中,字符串就像其他对象一样是对象。Java中String的一个有趣之处在于它是不可变的。不可变意味着字符串一旦创建就不能更改或修改。我们将在后面的文章中讨论不变性,不要让我们忘记它。
字符串字面量只是双引号内的字符序列。
String str = "codekru" ;
首先,我们希望你熟悉字符串和内存,因为它提供了在Java中如何存储和访问字符串的见解。它将进一步帮助您更好地理解字符串的各种概念。
关于字符串和内存的事实
任何编程语言的关键目标之一是有效地使用内存。随着应用程序的增长,字符串文字可能会占用程序的大量内存。因此,为了使Java更高效,JVM留出了一个称为String常量池的特殊内存区域。
当编译器遇到一个String文字时,它会检查String池,看看是否已经存在一个相同的String。如果该字符串已经存在,则对新文本的引用将定向到该现有字符串,因此不会创建新的String文本。
那些在堆和字符串常量池之间混淆的人,不要担心,记住,我们说过JVM会留出一个特殊的内存区域。这个特殊的区域在堆本身之内。下面的图表可以进一步说明这一点。
现在,你一定开始明白为什么不变性在字符串中至关重要了吧?
如果多个变量引用同一个String而不知道它,如果其中任何一个变量都可以改变String的值,那就太糟糕了。假设有两个变量s1和s2引用同一个String(“codekru”),那么如果s1以某种方式改变了String的值,它也会影响s2。
你现在可能会说,如果有人覆盖了String类的功能呢?不会在池里引起问题的东西吗?
这是String类被标记为final的主要原因之一。没有人可以覆盖String方法的功能。因此,我们可以放心,String对象将始终是不可变的。
How to create new Strings如何创建新字符串
创建字符串有很多方法,但我们将讨论最常用的方法。
Using String literals使用字符串文字
我们必须将字符串写在双引号中,就是这样。让我们假设池中还不存在String对象。
String str = "codekru" ; // creates one String object and one reference variable
它将在String池中创建“codekru”,str变量将引用它。
如果我们创建另一个变量s2,使用相同的字符串文字“codekru”呢?现在,它不会创建另一个字符串字面量。相反,它将引用已经存在的一个,这可以通过使用==运算符来证明。
public class Codekru {public static void main(String[] args) {String str = "codekru";String s2 = "codekru";if (str == s2) {System.out.println("referring to the same instance"); // will print this} else {System.out.println("Not referring to the same instance");}}
}
产出-
referring the same instance
Using String() constructor使用String()构造函数
We can also create a String object using the new keyword.
我们也可以使用new关键字创建一个String对象。
String str = new String("Codekru"); // creates two objects and one reference variable
由于我们使用了new关键字,Java将在普通(非池)内存中创建一个新的String对象,str将引用它。除此之外,文字“codekru”也将被放置在池中。
让我们尝试使用相同的字符串字面量(“codekru”)创建一个新对象
public class Codekru {public static void main(String[] args) {String str = new String("codekru");String s2 = new String("codekru");if (str == s2) {System.out.println("referring to the same instance");} else {System.out.println("Not referring to the same instance");}}
}
产出-
Not referring to the same instance
因此,我们可以看到每次使用new关键字后都会创建一个新的String对象。
现在,让我们回到String的不变性概念。看看下面的程序。
public class Codekru {public static void main(String[] args) {String str = "hello";str = str.concat(" codekru");System.out.println(str);}
}
产出-
hello codekru
现在,似乎弦已经改变了。之前是“你好”现在变成了“你好codekru”那么,关于String永远不能被更改或修改的说法是什么呢?
这里发生的是String本身没有改变。它只是创建了一个新的String,“hello codekru”,我们的变量现在只是指向它。所以,现在,我们在堆中有两个字面值。一个是“你好”,另一个是“你好codekru”。
Java字符串方法
Java为我们提供了许多方法来访问和执行对String的各种操作。其中一些列在下面-
charAt(int index)
:返回在指定索引处的字符值。codePointAt(int index)
:返回指定索引处的字符(Unicode码点)。compareTo(String anotherString)
:按字典顺序比较两个字符串。concat(String str)
:将指定字符串连接到此字符串的结尾。contains(CharSequence s)
:如果且仅如果此字符串包含指定的字符序列,则返回true
。endsWith(String suffix)
:检查字符串是否以指定的后缀结束。equalsIgnoreCase(String anotherString)
:在忽略大小写的情况下比较两个字符串。length()
:返回字符串的长度。indexOf(int ch)
:返回指定字符在此字符串中第一次出现的索引。indexOf(String str)
:返回指定子字符串在此字符串中第一次出现的索引。isEmpty()
:如果字符串的长度为0,则返回true
。strip()
:返回移除了所有前导和尾随空白字符的字符串。split(String regex)
:根据匹配给定的正则表达式的位置拆分此字符串。startsWith(String prefix)
:检查字符串是否以指定的前缀开始。substring(int beginIndex)
:返回从指定索引处开始的字符串的子字符串。toCharArray()
:将字符串转换为新的字符数组。toLowerCase()
:将此字符串中的所有字符转换为小写。toUpperCase()
:将此字符串中的所有字符转换为大写。valueOf()
(注意:此处的描述可能不完整,因为valueOf
有多个重载版本):返回参数的字符串表示形式。trim()
:返回移除了所有前导和尾随空格的字符串。