String类:
代表字符串, java程序中的所有字符串字面值(如, "abc")都是此类的实例实现
String是一个final类,代表不可变的字符序列
a: 当对字符串进行赋值时,需要重新指定内存区域不能使用原有value进行赋值
字符串是常量是用双引号引起来的,他们的值再创建后不可以修改
String对象的字符内容是存储再一个字符数组Value[]中的
字符串常量池中是不会存储相同的字符串
字符串数据的存储
字符串常量 String str1 = "字符串1"; 此时的字符串数据时声明在javaee方法区中的字符串常量池 字符串对象: String str2 = new String("老张"); 此时会创建两个对象一个 str2先指向堆中的结构然后底层的char【】数组又指向常量池的数据 一个时堆空间中的new结构,一个是char【】对应的常量池中的数据“老张”
表现:
String对象的创建
String name = "hello"; String的值底层都是存储再char [] 数组内 // 本质上this.value = new char[0]; string s1= new String() ; // this.value = ori.value String s2 = new String(String ori)
字符串对象的存储
首先会指向堆空间中的地址值,然后堆空间中的char【】数组地址值会指向常量池中的数据
字符串对象分为: 常量 和 非常量对象
String常量: 创建是不带new String name = "老王";
非常量: 创建是带new : String name = new String("老王");
字符串常量: String name = "老王"; 字符串非常量对象: String name = new String("老王");
放置的位置:
字符串常量放置在常量池内, 常量池内相同的值共享
非常量对象放置在堆中,值不可以共享
存储位置不同:
字符串常量放置在常量池内, 常量池内相同的值共享
非常量对象放置在堆中,值不可以共享
常量池内的值是可以共享的 我们定义的时候可以不用再开辟其余的空间了,这种方法省消耗
String再创建的时候value存储的位置也是不同的,虽然底层都是默认存储再char[] 中,但是 其存储的位置有时也是不同的
// 通过字面量定义的方式, 此时的s1的数据 声明再方法区中字符串常量池中 String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2); // true // new+构造器的方式此时的s3保存的地址值 是数据在堆中开辟的新空间保存的地址值 String s3 = new String("javaEE");
常量对象和非常量对象既然存储不同那么值肯定不能用==
常量对象非常量对象练习题:
求出下面输出的内容
// 通过字面量的定义方式: 此时的s1 和s2 定义在字符串常量池中 String s1 = "javaEE"; String s2 = "hadoop"; String s3 = "javaEEhadoop"; String s4 = "javaEE"+"hadoop"; String s5 = s1 +"hadoop"; String s6 = "javaEE"+s2; String s7 = s1+s2; String s8 = s6.intern(); System.out.println(s3 == s4); // System.out.println(s3 == s5); // System.out.println(s3 == s6); // System.out.println(s3 == s7); // System.out.println(s5 == s6); // System.out.println(s5 == s7); // System.out.println(s6 == s7); // System.out.println(s3 == s8); //
结果:
true false false false false false false true
因为携带变量名的都是存储在堆空间中的不是存储在常量池中,因为变量名拿到的都是讲指向堆中的地址值
结论:
1: 常量与常量的拼接在常量池内,且常量池内不会存储相同的内容的常量,同一个常量池中的常量地址都相同 2: 只要一个是变量,那么结果就是堆中,堆中的值都是地址不同的 3: 如果拼接的结果调用intern()方法,返回值就在常量池中
总结:
String 的使用 1:String的声明是使用一对 " " 引起来表示的 2: String 的声明为final的不可被继承 3: String 实现了Serializable接口 可序列化, 表示字符串是支持序列化 实现了Comparable接口 表示String可以比较大小 4: String在内部定义了final, char[] value用于存储字符串数据 5: String代表一个不可变的字符序列, 简称不可变 体现: a: 当对字符串重新赋值时 需要重写指定内存区域赋值, 不能使用原有的value进行赋值 b: 当对现有的字符串进行连接操作时重新赋值后, 也需要重新指定内存区域 c: 当调用String的replace()方法修改字符串时,也必须重新指定内存区域 *** 6: 通过字面量的方式(区别于new) 给一个字符串赋值 String name = "老王";此时的字符串声明在字符串常量中 7: 字符串常量池中是不会存储相同内容的字符串的
面试题:
1:
String s = new String("abc"); 方式创建对象, 在内存中创建了几个对象
创建了两个对象,
第一个是堆空间中new的结构 第二个是char[] 数组 ,对应的常量池中的数据"abc"
2:
public class StringTestTwo { public static void main(String[] args) { StringTT stringTT = new StringTT(); stringTT.change(stringTT.str, stringTT.ch); System.out.println(stringTT.str+"and"); stringTT.change("laowang", new char[]{'0'}); System.out.println(stringTT.ch); // best } } class StringTT{ String str = new String("good"); char [] ch = {'t', 'e', 's', 't'}; public void change(String str , char [] ch){ str = "test ok"; ch[0] = 'b'; System.out.println(str); } }
解答:
test ok
goodand 因为String是不可变的你的变了 但是我的仍然不变
test ok
best
String 的操作方法
int length():返回字符串的长度: return value.length char charAt(int index): 返回某索引处的字符return value[index] boolean isEmpty():判断是否是空字符串:return value.length == 0 String toLowerCase():使用默认语言环境,将 String 中的所有字符转换为小写 String toUpperCase():使用默认语言环境,将 String 中的所有字符转换为大写 String trim():返回字符串的副本,忽略前导空白和尾部空白 boolean equals(Object obj):比较字符串的内容是否相同 boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大 小写 String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+” int compareTo(String anotherString):比较两个字符串的大小 a.compareTo(b) 返回为正数表示a1>a2, 返回为负数表示a1<a2, 返回为0表示a1==a2; String substring(int beginIndex):返回一个新的字符串,它是此字符串的从 beginIndex开始截取到最后的一个子字符串。 String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字 符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。 boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束 boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始 boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的 子字符串是否以指定前缀开始 boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列 时,返回 true int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引 int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出 现处的索引,从指定的索引开始 int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引 int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后 一次出现处的索引,从指定的索引开始反向搜索 注:indexOf和lastIndexOf方法如果未找到都是返回-1 String replace(char oldChar, char newChar):返回一个新的字符串,它是 通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使 用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。 String replaceFirst(String regex, String replacement) : 使 用 给 定 的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。 boolean matches(String regex):告知此字符串是否匹配给定的正则表达式。 String[] split(String regex):根据给定正则表达式的匹配拆分此字符串。 String[] split(String regex, int limit):根据匹配给定的正则表达式来拆分此 字符串,最多不超过limit个,如果超过了,剩下的全部都放到最后一个元素中。
eg:
String.length() // 求出字符串的长度
// 求出String 字符串的长度 String.length() System.out.println(name.length()); // 2 System.out.println(EnglishName.length()); // 7
String.charAt() 返回指定索引中字符串中的内容
// 返回指定索引中的字符串中的字符 String.charAt(index); 不要以为只能怼字符串中的字符使用 还可以对汉字使用 System.out.println(name.charAt(1)); // 王 System.out.println(EnglishName.charAt(3)); // w
isEmpty() 判断字符串是否是空
// isEmpty() 判断字符串是否是空 String s1 = ""; System.out.println(name.isEmpty()); // false System.out.println(s1.isEmpty()); // true
toLowerCase() 字符串所有的字母都转为小写
// toLowerCase() 将String中的字符全部小写 String s2 = "Laowang"; String lowerCase = "你好WOde"; System.out.println(lowerCase.toLowerCase()); // 你好wode System.out.println(name.toLowerCase()); // 老王 汉字不会报错 System.out.println(s2.toLowerCase()); // L小写 laowang
toUpperCase() 字符串中所有的字母都大写
// toUpperCase() 将String中的字符全部大写 System.out.println(EnglishName.toUpperCase()); // LAOWANG
trim() 祛除首尾空格
// trim() 去除字符串首尾的空格 String s3 = " ni "; System.out.println(s3.trim());
equals() 比较两个字符串内容是否相同
== 比较的是内存地址值, equals() 比较的是大小
// equals() 比较字符串中的内容是否相同 System.out.println(name.equals(EnglishName)); // false
equalsIgnoreCase() 也是比较两个字符串大小,忽略大小写
// equalsIgnoreCase() 和equals()相同只是忽略大小写 String s4 = "LAOLI"; String s5 = "laoli"; System.out.println(s4.equalsIgnoreCase(s5)); // true
concat() 拼接,相等于"+",把两个字符串相加一起
// concat() // 拼接 把两个字符串拼接再一起 ,相当于+ System.out.println(name.concat(EnglishName)); // 老王laowang
contains(String str) 匹配, 判断字符串中是否有str
// contains() 判断当前字符串是否包含此字符串 String testOne = "nishi老王吗?"; System.out.println(testOne.contains("老王")); // true
indexOf(int n) 求出字符第一次出现的下标, 求出n在字符串中的下标位置
// indexOf("str")此字符串再当前字符串中第一次出现的位置 返回下标
String str1 = "helloWorld";
System.out.println(str1.indexOf("ll")); // 2
indexOf() 也可以判断这字符串在当前的位置是多少
// indexOf("str", int) 指定字符在此字符串中第一次出现的位置 不对就是-1 System.out.println(str1.indexOf("ll",2)); // 2
lastIndexOf() // 当前字符在字符串中最后出现的位置
//lastIndexOf() // 当前字符在字符串中的最后位置 返回下标 System.out.println(name.lastIndexOf("王")); // 1
替换: replace() 替换一个 replcaeAll() 替换所有
replace(String str, String str1) 替换, 将当前字符串中的str替换为str1
replaceAll(String str, String str1) 将当前字符串中的 所有str都替换为str1
String replcaeValue = "我是你的老王爸爸"; System.out.println(replcaeValue.replace("我是", "他是")); // 他是你的老王爸爸, 替换一个内容 System.out.println(replcaeValue.replaceAll("爸","奶")); // 我是你的老王奶奶 , 替换所有,把爸都替换成奶
subString(int, start, int end)截取字符串, 从当前字符串中截取中子字符串 从下标start截取到下标end
String replcaeValue = "我是你的老王爸爸"; System.out.println(replcaeValue.substring(1)); // 从下标1到最后, 是你的老王爸爸 System.out.println(replcaeValue.substring(0,3)); // 下标0-3 我是你
endsWith(String str) 测试当前字符串是不是以str结尾的
String endsWithValue = "老王你是"; System.out.println(endsWithValue.endsWith("你")); // false System.out.println(endsWithValue.endsWith("是")); // true
startsWith(String str) 测试当前字符串是不是以str开始的
System.out.println(endsWithValue.startsWith("老")); // true System.out.println(endsWithValue.startsWith("王")); // false
startsWith(String str, int n) 亦可以判断某下标是否是某个字符串, 判断当前字符串的下标n是否是str
System.out.println(endsWithValue.startsWith("你", 2)); // true 当前字符串的下标2是你
split()切割 拆解字符串,将字符串按照某个特定内容切割并放在一个数组内
split()特殊字符 分割的时候使用:
关于点的问题是用 : String.split("[.]"); String..split("\.") ; 关于竖线的问题用 : String.split("\|"); 关于星号的问题用 : String.split("\*"); 关于斜线的问题用 : Sring.split("\\");
eg:
str.split("s") 将字符串str按照内容s来切割为一个数组类型的内容
strOne = "TestStr" //spilt String [] strings = strOne.split("s"); for (String str:strOne.split("s") ) { System.out.println(str); } // Te tStr
String与其他结构的转化
String 与基本数据,包装类的转化
String 与基本数据类型, 包装类的之间的转换
String ----> 基本数据类型 包装类 : 调用包装类的parseXXX(str)
基本数据类型 包装类 ----> String 调用String重载的ValuesOf(xxx)
String age = "123"; int age1 = Integer.parseInt(age); System.out.println(age1); System.out.println(String.valueOf(age1));
String ---> char []
字符串转化为char 数组,
String ---> char [] 调用String的toCharArray() char [] ----> String 调用String的构造器
eg:
// char [] ---> String 调用String 的构造器 char [] chars = new char []{'b', 'v'}; String charStr = new String(chars); System.out.println(charStr); // String ---> char [] 调用String的toCharArray() String strChar = "老王"; char [] chars1 = strChar.toCharArray(); System.out.println(chars1); // 老王
String ---> byte [] 调用String的getBytes()
// String ---> byte [] 调用String的getBytes()
// byte[] ---> String 调用String的构造器
/*
. 编码: String ----> 字节 byte [] (看得懂--->看不懂)
解码: byte [] 字节----> String (看不懂---> 看得懂)
*/
String str4 = "abc中国";
byte [] bytes = str4.getBytes();
System.out.println(Arrays.toString(bytes));
// byte [] ---> String
System.out.println(new String(bytes));
.
习题:
1: 下列程序运行的结果
class MayTwentySixPracticeTestOne{ String str = new String("good"); char [] ch = {'t','e','s','t'}; public void change(String str,char []ch){ str = "test ok"; ch[0] = 'b'; } } public static void main(String [] agrs){ MayTwentySixPracticeTestOne e = new MayTwentySixPracticeTestOne(); e.change(e.str,e.ch); System.out.println(e.str.concat("and")); System.out.println(e.ch); }
goodand
best
2:
public class StrExer { public static void main(String[] args) { ReplcaeOne replcaeOne = new ReplcaeOne(); System.out.println(replcaeOne.replcaeBuffer()); // abfedcg System.out.println(replcaeOne.replcaeChar()); // abfedcg } } class ReplcaeOne { // 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反转为”abfedcg” String str = "abcdefg"; String strStart = str.substring(0, 2); String strEnd = str.substring(6); String strSub = str.substring(3, 6); // StringBuffer 解法 public String replcaeBuffer() { StringBuffer stringBuffer = new StringBuffer(strSub); strSub = stringBuffer.reverse().toString(); // 翻转后再转为String return strStart.concat(strSub).concat("c").concat(strEnd); } // char [] 解法 public String replcaeChar() { String reverse = ""; char [] chars = strSub.toCharArray(); for (int i = chars.length -1; i >=0 ; i--) { // 把所有的 内容反着提取出来 reverse += chars[i]; } return strStart.concat(reverse).concat("c").concat(strEnd); } }
1. 模拟一个trim方法,去除字符串两端的空格。 2. 将一个字符串进行反转。将字符串中指定部分进行反转。比如“abcdefg”反 转为”abfedcg” 3. 获取一个字符串在另一个字符串中出现的次数。 比如:获取“ ab”在 “abkkcadkabkebfkabkskab” 中出现的次数 4.获取两个字符串中最大相同子串。比如: str1 = "abcwerthelloyuiodef“;str2 = "cvhellobnm" 提示:将短的那个串进行长度依次递减的子串与较长的串比较。 5.对字符串中字符进行自然顺序排序。 提示: 1)字符串变成字符数组。 2)对数组排序,选择,冒泡,Arrays.sort(); 3)将排序后的数组变成字符串。