java中,字符串属于对象。java提供了String类来创建和操作字符串。
String
字符串常量
创建
//最简单的方法
String s1 = "蓦然回首灯火阑珊";
遇到字符串常量时(这里的值是“蓦然回首灯火阑珊”),编译器会使用该值创建一个String对象。
或者像普通的对象 一样使用关键字和构造方法来创建String对象。
String类共11种构造方法,提供不同的参数初始化字符串。
注意:String类不可改变。一旦创建了String对象,它的值就无法改变。
因此,如果你需要对字符串作很多修改的话,应该选择StringBuffer和StringBuilder类。
字符串长度
用于获取有关对象信息的方法,称为访问器方法。
String类的一个访问器方法是length()方法,返回字符串对象包含的字符数。
连接字符串
String提供了两个连接字符串的方法。
//1、concat()
String1.concat(String2);
//2、直接用"+",更常用
"hello" + "txl" + "!";
创建格式化字符串
输出格式化数字:printf()和format()。
System.out.println("浮点变量值:" + "%f,整数的值: " + "%d,字符串: " + "%s " ,fV,iV,sV);
//String 的类方法 format返回一个String对象。
//上式可以写成:
String s1;
s1 = String.format("浮点变量值:" + "%f,整数的值: " + "%d,字符串: " + "%s " ,fV,iV,sV);
String 方法
方法 | 描述 |
---|---|
char charAt(int index) | 返回字符串指定索引处的字符 |
int compareTo(String str) | 一次比较字母的ascII值返回差值 |
int compareToIgnoreCase(String str) | 忽略大小写,同上 |
String concat(String str) | 在字符串的末尾补上str |
boolean contentEquals(StringBuffer sb) | 字符串与sb有相同顺序的字符返回真 |
static String copyValueOf(char[] data) | 返回字符串中表示该字符数组的字符串 |
boolean equals(Object obj) | 给定对象与字符串相等返回true |
boolean equalsIgnoreCase(String str) | 忽略大小写同上 |
byte[] getBytes() | 没加参数的话使用平台默认的字符集将此String编码为byte序列;方法可以有一个字符串参数,为编码格式 |
void getChars(int beg,int end,char[] des,int desBeg) | 将字符从字符串复制到目标字符数组 |
int indexOf(int ch/String str) | 返回字符和字符串第一次在字符串中出现的索引 |
int length() | 字符串长度 |
boolean matches(string regex) | 字符串是否匹配给定的正则表达式 |
String replace(char c1,char c2) | 返回一个新的字符串-用c2代替c1 |
String[] split(String regex) | 按正则表达式拆分成字符串数组 |
Sring substring(int begn) | 返回字符串的子字符串 |
char[] toCharArray() | 字符串转为字符数组 |
String toLowerCase() | 所有字符小写 |
String trim() | 返回一个副本,忽略前导空白和尾部空白 |
注意:String类不可改变。
//1
String s = "Google";
System.out.println(s);//输出为hello
String s = "Hello";
System.out.println(s);//输出为TxL
String对象改变了?
是有些东西改变了,但是改变的不是String对象,而是别的东西。
和基本数据类型不一样:
//2
int a = 2;
a = 3; //a改变,原来的2被覆盖消失,而1中的"hello"并没有消失,原来的s不再**引用**"Google"对象,改为引用"Runoob"。)
下图截自菜鸟教程
因此,答案出来了。改变的是String对象的引用,而不是String对象本身。通俗的来讲,只是改变了箭头的指向。
测试1:
String s1 = "abc"; // 常量池
String s2 = new String("abc"); // 堆内存中
System.out.println(s1==s2); // false两个对象的地址值不一样。
System.out.println(s1.equals(s2)); // true两个对象的字符一样
测试2:
String s1="a"+"b"+"c"; //编译时能确定s1
String s2="abc"; //直接引用"abc",因为abc已经存在
System.out.println(s1==s2); //比较s1s2的值即比较地址,两个均指向同一"abc",因此结果为true
System.out.println(s1.equals(s2)); //true
java 中常量优化机制,编译时 s1 已经成为 abc 在常量池中查找创建,s2 不需要再创建。
测试3:
String s1="ab";
String s2="abc";
String s3=s1+"c"; //编译时不能确定s3
System.out.println(s3==s2); // false
System.out.println(s3.equals(s2)); // true
问题:new String(“abc”)创建了几个对象 ?
答案:准确的说是1或2个。若常量池中存在"abc",则只创建一个对象;若常量池中不存在"abc",则先创建"abc"对象,再new String()创建一个放在堆中,共2个。
通过new创建出对象是在堆中进行的,在堆中进行对象生成的过程是不会检测该对象是否已经存在的。因此,new出来的对象一定是不同的对象,即使字符创的内容相同。
再次分析:
//比较下面几个语句的区别
String s1 = "hello"; //将对象放入常量池中。
String s2 = "TxL"; //将字符串常量放入常量池中
String str1 = "hello" + "TxL"; //编译时就确定了str1,为helloTxL,并将此字符串常量放入常量池中.
//至此,常量池中共有三个对象。因此str1 引用指向常量池中的"helloTxL"
String str2 = s1 + "TxL"; //在堆中分配。
String str3 = s1 + s2; // + 会在堆中建立起两个String对象,对象的值是"hello","TxL",即从常量池中赋值这两个值然后在堆中创建两个对象。然后在创建对象str3.共创建了3个对象。
分析:对字符串赋值时,若=右侧含有1个或更多字符串引用时,在堆中建立一个字符串对象,返回引用。
字符串实际上是一个char数组,内部封装了一个char数组。并且被final修饰。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
//String中所有的方法,都是对于char数组的改变。因此只要对他改变,方法内部均返回一个新的String实例
区别:length()、length、size()。
直接通过例子:
String[] array = {"hello,","TxL","!"};
String a = "Ting";
List<String> list = new ArrayList<>();
list.add("xiao");
list.add("liu");
System.out.println(array.length());
System.out.println(a.length);
System.out.println(list.size());
输出结果为:
3
4
2
总结:
- length()用于数组
- length用于字符串对象
- size()用于泛型集合
StringBuffer
和String类不同的是,StringBuffer和StringBuilder类的对象能够被多次的修改,并且不产生新的未使用的对象。(StringBuilder在java5提出,和StringBuffer最大的不同在于StringBuilder的方法不是线程安全的,即不能同步访问)。因此,若要线程安全-StringBuffer类,否则多数情况下,StringBuilder类。
StringBuffer方法
方法 | 描述 |
---|---|
StringBuffer append(String s) | 将s添加到字符串结尾 |
StringBuffer reverse() | 将字符串反转并取代原字符串 |
StringBuffer delete(int start,int end) | 移除字符串 |
StringBuffer insert(int offset,String s) | 将s插入在offset处 |
StringBuffer replace(int start,int end,String s) | 将s代替指定位置的字符串 |
void setCharAt(int index,char c) | 更改字符 |
String substring(int start) | 返回一个新的String对象,子序列字符串 |
String toString() | 返回字符串形式 |
总结
- String对象长度大小不变
- StringBuffer和StringBuilder对象长度可变
- StringBuffer线程安全,StringBulder线程不安全
- StringBuffer快