关于字符串
字符串的特点
- 一般类的对象要用new关键字,但是java程序中所有双引号字符串,都是String的对象,不管new不new;
- 字符串内容不可改变,因此可以共享使用,以节省内存;
- 每个字符串的底层存储原理是个字节数组 byte[ ],而外观上像是字符数组 char[ ] ;
- java.lang包是java语言的核心,它提供了java中的基础类。包括基本Object类、Class类、【String类】、基本类型的包装类、基本的数学类等等最基本的类,使用String类时不需要先import。
字符串的创建方法
常见的创建字符串的方式:1种直接创建方式、3种构造方法,如下:
public class StringDemo {
public static void main(String[] args) {
// 最香的方法,即便没new,str0仍然是String的对象
String str0 = "Hello";
System.out.println("最简单的直接创建字符串:" + str0);
// 下面是三种new的方法
String str1 = new String();
System.out.println("创建一个空字符串:" + str1);
// 看似字符数组char的拼接
char[] charArray = {'A' , 'B' , 'C'};
String str2 = new String(charArray);
System.out.println("利用字符数组创建字符串:" + str2);
// 实则在底层以字节数组byte存储
byte[] byteArray = {97, 98, 99};
String str3 = new String(byteArray);
System.out.println("利用字节数组创建字符串:" + str3);
}
}
/*
结果:
最简单的直接创建字符串:Hello
创建一个空字符串:
利用字符数组创建字符串:ADC
利用字节数组创建字符串:abc
*/
常量池
常量池开辟在堆内存中,用双引号直接创建的字符串存放在常量池中,而new出来的字符串不在常量池。
字符串内容的比较——A.equals(B)
-
基本数据类型 byte、short、char、int、long,、float、double、boolean 之间的比较,用双等号==,比较的是它们的值。
-
引用数据类型用==进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。Java中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址。但在一些类库当中这个方法被覆盖掉了,如String、Integer、Date在这些类中equals有其自身的实现,而不再是比较类在堆内存中的存放地址了。
对于引用数据类型之间进行equals比较,在没有覆写equals方法的情况下,他们之间的比较还是基于他们在内存中的存放位置的地址值的,因为Object的equals方法也是用双等号进行比较的,所以比较后的结果跟双等号的结果相同,但String类中equals有其自身的实现,比较的是字符串内容。
String类型属于引用类型,变量中存储的是地址,对应的地址存储数据,直接用==进行的是地址的比较,同一地址返回 true。
想要比较字符串内容用A.equals(B)。(注意:基本类型的比较只能用双等号来比较,不能用equals,没有意义。比如a=3,b=3,a.equals(b)会编译报错)
public class StringDemo {
public static void main(String[] args) {
String str1 = "Hello";
String str2 = "Hello";
char[] array = {'H' , 'e' , 'l' , 'l' , 'o'};
String str3 = new String(array);
/*
对于引用类型来说,两个等于号进行的是地址的比较,同一地址为true。
所以直接创建字符串String str1="Hello";String str2="Hello",
会发现str1、str2所指的对象是同一个,就处在常量池中。
由于str1和str2地址相同,所以str1==str2的结果为true。
而new出来的字符串虽然也在堆中,但不在常量池,所以str1==str3结果为false。
*/
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // false
/*
我非要想比较字符串的内容是否相同,那也是可以的。
用 equals(Object obj),如果内容一样A.equals(B)返回true。
*/
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals(str3)); // true
System.out.println(str3.equals("Hello")); // true
System.out.println("Hello".equals(str1)); // true
/*
A.equals(B)和B.equals(A)效果相同,只要内容一样(区分大小写)就返回true,
但是如果进行的是一个常量和一个变量,那么常量字符串推荐写在前面。
即推荐写"Hello".equals(str),避免空指针异常,示例如下:
*/
String str4=null;
System.out.println("Hello".equals(str4)); // false
System.out.println(str4.equals("Hello")); // java.lang.NullPointerException
// 担心空指针问题也可以导入Objects类,再用 Boolean b = Objects.equals(a1,a2)
/*
另外还有一种方法也可比较字符串内容,但是不区分大小写
从方法名A.equalsIgnoreCase(B)也可以看出来:
*/
String str5="Java";
String str6="java";
System.out.println(str5.equals(str6)); // false
System.out.println(str5.equalsIgnoreCase(str6)); // true
}
}
常规操作(长度、索引、查找)
获取长度 ——str.length()
获取第3个字符是什么 ——str.charAt(2)
查找“我们”在字符串中的位置 ——str.indexOf(“我们”)
public class StringDemo {
public static void main(String[] args) {
// 获取字符串长度
int length = "khrfiaeh".length();
System.out.println("字符串长度为:" + length);
// 拼接出一个新字符串
String str1 = "Hello";
String str2 = "World";
String str3 = str1.concat(str2);
System.out.println(str3);
// 获取指定索引位置的单个字符
char at = "Java".charAt(2);
System.out.println("2号索引位置的字符是:" + at);
// 查找参数字符串在原字符串中第一次出现的索引位置
String original = "好好学习天天向上";
int i = original.indexOf("天天");
System.out.println("天天第一次出现的位置"+i);
// 若没匹配到参数字符串,则会返回-1
int j = original.indexOf("地地");
System.out.println("地地第一次出现的位置"+j);
}
}
/*
结果:
字符串长度为:8
HelloWorld
2号索引位置的字符是:v
天天第一次出现的位置4
地地第一次出现的位置-1
*/
字符串的截取方法——str.substring(4,7)
截取索引5以后的字符 ——str.substring(5)
截取索引4到索引6的字符[前闭后开] ——str.substring(4,7)
// 截取出从参数位置开始的所有字符给新字符串str1
String str1 = "HelloWorld".substring(5);
System.out.println(str1); // World
String str2="HelloWorld".substring(4,7); // 前闭后开
System.out.println(str2); // oWo
字符串的转换方法——str.toCharArray()
转换为字符数组 ——str.toCharArray()
转换为字节数组 ——str.getBytes()
// 将字符串转换为字符数组
char[] ch = "Java".toCharArray();
System.out.println(ch.length);
// 注意数组长度是.length 而不是.length()
System.out.println(ch[2]);
//4
//v
// 将字符串转换为字节数组
byte[] by="Java".getBytes();
for (int i = 0; i < by.length; i++) {
System.out.print(by[i]+"、");
}
//74、97、118、97、
字符串的替换方法——str.replace(old,new)
替换 ——str.replace(old,new)
String str1="垃圾法师你他妈会不会玩儿啊,真垃圾";
String harmoniousStr1 = str1.replace("他妈", "**");
String harmoniousStr2=harmoniousStr1.replace("垃圾","**");
System.out.println(harmoniousStr2);
//**法师你**会不会玩儿啊,真**
字符串的分割方法——str.split(",")
按逗号分割 ——str.split(",")
String str1 = "aaa,bbb,ccc,ddd";
String[] array1 = str1.split(",");
for (int i = 0; i < array1.length; i++) {
System.out.println(array1[i]);
}
String str2 = "aaa.bbb.ccc.ddd";
// 点在正则表达式中有特殊含义,需要写为\\.
String[] array2 = str2.split("\\.");
for (int i = 0; i < array2.length; i++) {
System.out.println(array2[i]);
}
练习:对输入的字符串的字符进行分类计数
键盘输入字符串,对其中的大小写、数字、符号分别进行计数并输出
import java.util.Scanner;
public class StringDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String input = sc.next();
int Upper = 0;
int Lower = 0;
int Number = 0;
int Other = 0;
char[] charArray = input.toCharArray();
for (int i = 0; i < charArray.length; i++) {
char ch = charArray[i];
// 不用去查ASCII码,直接写就行
// 因为前面提过char类型进行运算会首先转为int
if (ch >= 'A' && ch <= 'Z') {
Upper++;
} else if (ch >= 'a' && ch <= 'z') {
Lower++;
} else if (ch >= '0' && ch <= '9') {
Number++;
} else {
Other++;
}
}
System.out.println("输入了大写字母" + Upper + "个");
System.out.println("输入了小写字母" + Lower + "个");
System.out.println("输入了数字" + Number + "个");
System.out.println("输入了符号" + Other + "个");
}
}
/*
请输入一个字符串:
UJI12345abcd,.;#&$
输入了大写字母3个
输入了小写字母4个
输入了数字5个
输入了符号6个
*/