Java学习
- String字符串
-
- 概述
- String类的特点
- String字符串常量池
- String字符串的构造方法
- String字符串的23个常用方法
- StringBuilder类/StringBuffer类
-
- StringBuilde构造方法
- append方法
- toString方法
- StringBuilder和StringBuffer的区别
- 练习一
- 练习二
- 扩展(面试题)
String字符串
概述
java.lang.String类代表字符串。
API当中说:Java程序中的所有字符串字面值(如"abc")都作为此类的实例实现。
其实就是说:程序当中所有的双引号字符串,都是String类的对象。(就算没有new,也照样是。)
String类的特点
对String在内存存储方面的理解:
1.字符串一旦创建内容永不可变,每当你觉得字符串变了的时候,必然就是创建了新的字符串 。【重点】
2.正因为字符串不可改变,所以字符串是可以共享使用的。
3.字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组。
4.双引号括起来的字符串存储在字符串常量池中。
5.字符串的比较必须使用equals方法。
6.String已经重写了toString()和equals()方法。
String字符串常量池
在JDK当中双引号括起来的字符串,例如:“abc”,“def”,都是直接存储在“方法区”的“字符串常量池”当中的。
为什么SUM公司把字符串存储在一个“字符串常量池”当中呢?因为字符串在实际开发中使用太频繁,为了执行效率,所以把字符串放到了方法区的字符串常量池当中。
对于基本类型来说,==是进行数值的比较。
对于引用类型来说,==是进行【地址值】的比较。
// i变量中保存的是100这个值
int i = 100;
//s变量中保存的是字符串对象的内存地址。
//s引用中保存的不是"abc",而是指向"abc"这个数据的内存地址
String s = "abc";
//分析以下两行代码,一共创建了几个对象。
String s1 = new String("hello");
String s2 = new String("hello");
//一共3个对象:方法区字符串常量池中有一个"hello",堆内存当中两个String对象。
String字符串的构造方法
String s = " " ;
String s = new String(" ");
String s = new String(byte数组);
String s = new String(byte数组,起始下标,长度);
String s = new String(char数组);
String s = new String(char数组,起始下标,长度);
举例:
public static void main(String[] args) {
//创建字符串对象最常用的一种方式
String s1 = "hello world!";
//s1这个变量中保存的是一个内存地址。//按说以下应该输出一个地址。
//但是输出一个字符串,说明string类已经重写了toString()方法。
System.out.println(s1); //helloworld!
System.out.println(s1.toString());//hello world!
//这里只常据常用的构造方法。
byte[] bytes = {97,98,99};//97是a,98是b,99是c
String s2 = new String(bytes);
//输出一个引用的时候,会自动调用toString()方法,默认Obiect的话,会自动输出对象的内存地址
//通过输出结果我们得出一个结论:String类已经重写了toString()方法。
// 输出字符串对象的话,输出的不是对象的内存地址,而是字符串本身。
System.out.println(s2.toString());//abc
System.out.println(s2);//abc
//String(字节数组,数组元素下标的起始位量,长度)
// byte数组中的一部分转换成字符串。
String s3 = new String(bytes,1,2);
System.out.println(s3);//bc
//char数组全部转换成宇符串
char[] chars ={'你','好','呀','朋','友'};
String s4 = new String(chars);
System.out.println(s4); // 你好呀朋友
//将char数组的一部分转换成字符串
String s5=new String(chars,2,3);
System.out.println(s5); // 呀朋友
}
String字符串的23个常用方法
public static void main(String[] args) {
//1. char charAt(int index)
//获取指定索引位置的单个字符串
char c = "你好".charAt(1); // "你好"是一个字符串String对象,所以可以直接调用String类的方法。
System.out.println(c); // 输出:好
//2. int compareTo(String anotherString)
//字符串之间比较大小不能直接使用><,需要使用compareTo方法。
int result ="abc".compareTo("abc");
System.out.println(result);// 输出:0 解释:(等于0)代表前后一致 10-10=0
int result2="abcd".compareTo("abce");
System.out.println(result2);//输出:-1 解释:(小于0)前小后大 8-9=-1
int result3="abce".compareTo("abcd");
System.out.println(result3);//输出:1 解释:(大于0)前大后小 9-8=1
//拿着字符串第一个字母和后面字符串的第一个字母比较。能分胜负就不再比较了。
System.out.println("xyz".compareTo("yxz"));//输出:-1
//3. boolean contains(CharSequence s)
// 判断前面的宇符串中是否包含后面的子字符串。
System.out.println("HelloWorld.java".contains("java")); //输出:true
System.out.println("http://www.baidu.com".contains("https://")); //输出:false
//4. boolean endsWith(String suffix)
// 判断当前字符串是否以某个字符串结尾。
System.out.println("test.txt".endsWith(".java"));// 输出:false
System.out.println("test.txt".endsWith(".txt")); // 输出: true
System.out.println("fdsajklfhdkjlsahfjkdsahjklfdss".endsWith("ss")); //输出: true
//5. boolean equals(Object anObject)
//比较两个字符串必须使用equals方法,不能使用“==”
//equals方法有没有调用compareTo方法?老版本可以看一下。JDK13中并没有调用compareTo()方法
// equals只能看出相等不相等。
//compareTo方法(第二个方法)可以看出是否相等,并且同时还可以看出谁大谁小。
System.out.println("abc".equals("abc")); //输出: true
//6. boolean equalsIgnoreCase(String anotherString)
// 判断两个字符串是否相等,并且同时忽略大小写。
System.out.println("ABc".equalsIgnoreCase("abc"));//输出: true
//7. byte[] getBytes()
// 字符串对象转换成字节数组
byte[] bytes = "abcdef".getBytes();
for (int i = 0; i < bytes.length; i++) {
System.out.println(bytes[i]); // 输出: 97 98 99 100 101 102
}
//8. int index0f(String str)
//判断某个子字符串在当前字符串中第一次出现处的索引(下标)。 如果没有返回-1
System.out.println("oraclejavac++.netc#phppythonjavaoraclec++".indexOf("java"));// 输出:6
//9. boolean isEmpty()
// 断个字持事是否为“空字符串”,底层源代码调用的应该是字符串的lenath()方法。
// String s = " " ;
String s = "a";
System.out.println(s.isEmpty()); // 输出:false
//10. int length() 判断字符串长度
//面试题:判断数组长度和判断字符串长度不一样
//判断数组长度是length属性,判断字符串长度是length()方法。
System.out.println("abc".length());//输出: 3
System.out.println("".length());//输出: 0
//11. int lastIndexOf(String str)
// 判断某个子字符在当前字特串中最后一次出理的索引(下标)
System.out.println("oraclejavac++javac#phpjavapython".lastIndexOf("java"));//输出:22
//12. String replace(CharSequence target,CharSequence replacement) 替换。
//String的父接口就是:CharSequence
String ss ="http://www.baidu.com".replace("http://","https://");
System.out.println(ss);//输出:https://www.baidu.com/
// 把以下字符串中的"="替换成":“
String ss2 ="name=zhangsan&password=123&age=2".replace("=",":");
System.out.println(ss2);//输出: name:zhangsan&password:123&age:20
//13. String[] split(String regex)
// 拆分字符串
String[] ymd = "1980-10-11".split("-");//”1980-10-11"以“-”分隔符进行拆分。
for(int i=0; i<ymd.length; i++) {
System.out.println(ymd[i]);
}
String param="name=zhangsan&password=123&age=20";
String[] params = param.split("&"); //以“&”分隔符进行分割
for(int i = 0; i <params.length; i++) {
System.out.println(params[i]);
}
String str = "aaa bbb ccc";
String[] array2 = str.split(" "); //根据空格来切
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i]);
}
//14. boolean startsWith(String prefix)
// 判断某个字符串是否以某个子字符串开始。
System.out.println("http://www.baidu.com".startsWith("http")); //输出: true
System.out.println("http://www.baidu.com".startsWith("https")); //输出: false
//15. String substring(int beginIndex)参数是起始下标。
// 截取字符串
System.out.println("http://www.baidu.com".substring(7));//输出:www.baidu.com
//16. String substring(int beginIndex, int endIndex)
// beginIndex起始位置(包括)
// endIndex结束位置(不包括)
System.out.println("http://www.baidu.com".substring(7,10));//输出:www
//17. char[] toCharArray()
// 将字符串转换成char数组
char[] chars="你好呀朋友".toCharArray();
for(int i = 0; i< chars.length; i++){
System.out.println(chars[i]);
}
//18. String toLowerCase()
//转换为小写
System.out.println("AUIHGBUAYH".toLowerCase()); //输出:auihgbuayh
//19. String toUpperCase()
//转换为大写
System.out.println("HDHGhuhfi".toUpperCase()); // 输出:HDHGHUHFI
//20. String trim()
//去除字符串前后空白
System.out.println(" hello world ".trim() ); //输出:hello world
//21. String中只有一个方法是静态的,不需要new对象
//这个方法叫做valueOf()
//作用:将“非字符串”转换成“字符串”
String a = String.valueOf(true);
String b = String.valueOf(100);
String cc = String.valueOf(3.14);
//22. String concat(String str)
// 将当前字符串和参数字符串拼接成为新的字符串
String str11 = "heallo";
String str22 = "wordl";
String str33 = str11.concat(str22);
System.out.println(str33); //输出:heallowordl
//23. String replace(CharSequence oldString,CharSequence newString)
//将所有出现的老字符串替换成为新的字符串,返替换后的结果成为新字符串
//CharSequence意思就是说可以接受字符串类型
String str1 = "How do you do?";
String str2 = str1.replace("o","*");
System.out.println(str2); //输出:H*w d* y*u d*?
String lang1 ="会不会玩,傻逼,傻逼";
String lang2 = lang1.replace("傻逼","**");
System.out.println(lang2); //输出:会不会玩,**,**
}
StringBuilder类/StringBuffer类
stringBuffer/strinaBuilder可以看做可变长度字符串。
stringBuffer/stringBuilder初始化容量16.
stringBuffer/stringBuilder是完成字符串拼接操作的,方法名:append
stringBuffer是线程安全的。stringBuilder是非线程安全的。频繁进行字符串拼接不建议使用"+"
StringBuilde构造方法
public static void main(String[] args) {
// 空参数构造
StringBuilder bu1 = new StringBuilder();
System.out.println("bu1:"+bu1); //bu1:"" 默认空字符串
// 带字符串的构造方法
StringBuilder bu2 = new StringBuilder("abc");
System.out.println("bu2:"+bu2); //bu2:abc
//指定初始化容量的StringBuilder对象(字符串缓冲区对象)
//如何优化性能? 在创建对象的时候尽可能给定一个初始化容量,
//因为初始化容量是16,append方法底层在追加的时候,如果byte数组满了,会自动扩容
//所以最好减少底层数组的扩容次数,预估计一下,给一个大一些的初始化容量
//关键点:给定一个合适的初始化容量,可以提高程序的执行效率
StringBuilder bu3 = new StringBuilder(100);
}
append方法
public StringBuilder append (…): 添加任意类型的字符串样式,并返回当前对象自身
public static void main(String[] args) {
/*
StringBuilder的常用方法:
public StringBuilder append (...): 添加任意类型的字符串样式,并返回当前对象自身
*/
// 创建StringBuilder对象
StringBuilder bu = new StringBuilder();
//使用append方法往StringBuilder中添加数据
//append方法返回值是this,调用方法的对象bu this==bu
StringBuilder bu2 = bu.append("abc"); //把bu的地址赋值给bu2
System.out.println(bu); //"abc"
System.out.println(bu2); //"abc"
System.out.println(bu==bu2); // 引用类型比较的是地址 ture
//使用append方法无需接收返回值
//它里面可以添加任意内容
bu.append("abc");
bu.append(1);
bu.append(true);
bu.append(8.8);
bu.append('中');
System.out.println(bu); //abcabc1true8.8中 前面一个abc是上面的
/*
链式编程:方法返回值是一个对象,可以继续调用方法
*/
//它返回的还是StringBuilder对象,所以可以继续调用这个对象的方法
bu.append("abc").append(1).append(true).append(8.8).append('中');
}
toString方法
public String toString(): 将当前StringBuilder对象转换为String对象
public static void main(String[] args) {
//String->StringBuilder
String str = "hello";
System.out.println("str:"+str); //str:hello
StringBuilder bu = new StringBuilder("str");
//往StringBuilder中添加数据
bu.append("world");
System.out.println(bu); //strworld
//StringBuilder->String
String s = bu.toString();
System.out.println("s:"+s); //s:strworld
}
StringBuilder和StringBuffer的区别
StringBuilder和StringBuffer构造方法和append、toString方法使用方式都是一样的,
那么他们的区别是什么呢?
StringBuffer中的方法都有:synchronized关键字修饰。表示StringBuffer在多线程环境下运行是安全的。
StringBuilder中的方法都没有:synchronized关键字修饰,表示5tringBuilder在多线程环境下运行是不安全的。
StringBuffer是线程安全的。 StringBuilder是非线程安全的。
练习一
public class 按指定格式拼接字符串 {
public static void main(String[] args) {
int [] aa={1,2,3};
String bb = bb(aa);
System.out.println(bb);
}
public static String bb(int[] aa){
String str = "[";
for (int i = 0; i < aa.length; i++) {
if (i==aa.length-1){
str+="word"+aa[i]+']';
}else {
str+="word"+aa[i]+"#";
}
}
return str;
}
}
练习二
public class 统计输入字符串中各种字符的个数 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String next = sc.next();
int aa =0; //大写字母
int bb =0; //小写字母
int cc =0; //数字
int dd =0; //其他
char[] chars = next.toCharArray();
for (int i = 0; i < chars.length; i++) {
char ch = chars[i]; //当前单个字符
if ('A'<=ch && ch<='Z'){
aa++;
}else if ('a'<=ch && ch<='z'){
bb++;
}else if ('0'<=ch && ch<='9'){
cc++;
}else {
dd++;
}
}
System.out.println("大写字母有:"+aa);
System.out.println("小写字母有:"+bb);
System.out.println("数字有:"+cc);
System.out.println("其他字符有:"+dd);
}
}
扩展(面试题)
第一句“我看过源代码”要说,提高逼格,增加工资,嘿嘿嘿,本期到此结束,我们下期再见!