一、概述
java.lang.String 类代表字符串,Java程序中所有字符串文字都为此类
注意:
字符串内容是不会发生改变的,它的对象在创建后不能被更改
比如:
String name = "666";
name = "8wx";
这是两个字符串
java程序中所有的字符串文字都被实为此类的对象,字符串不可变,它的值在创建后不可被更改
二、创建String 对象的两种方式
1.直接赋值
String name = "马克诺弗";
2.new
构造方法 | 说明 |
---|---|
public String() | 创建空白字符串,不含任何对象 "" |
public String(String original) | 根据传入的字符串,创建字符串对象 |
public String(char[] chs) | 根据字符数组,创建字符串对象 |
public String(byte[] chs) | 根据字节数组,创建字符串对象 |
public class test {
public static void main(String[] args) {
//1.使用直接赋值的方式获取一个字符串对象
String s1 = "abc";
System.out.println(s1);
//2.使用new的方式来获取一个字符串对象
String s2 = new String();
System.out.println("@"+s2+"!");
//根据传入的字符串,创建字符串对象
String s3 = new String("abc");
System.out.println(s3);
//根据字符数组,创建字符串对象
char[] chs = {'a','b','c'};
String s4 = new String(chs);
System.out.println(s4);
//根据字节数组,创建字符串对象
byte[] bytes = {97,98,99};
String s5 = new String(bytes);
System.out.println(s5);
}
}
在内存方面:
当使用双引号直接赋值时,系统会检查字符串在串池中是否存在。存在即复用,不存在创建新的。而new出来的则不会复用,所以推荐直接赋值。
三、Java的常用比较方法
1、
String s1 = "abc"; String s2 = "abc"; System.out.println(s1 == s2);//true
2、
String s1 = "abc"; String s2 = "abd"; System.out.println(s1 == s2);//false
3、
String s1 = new String("abc"); String s2 = "abc"; System.out.println(s1 == s2);//false
所以
==号比的是什么?
1.基本数据类型——数据值
2.引用数据类型——地址值
所以引入两个比较字符串的方法:
1、boolean equals方法 —— 完全一样才是true,否则为false
2、boolean equalslgnoreCase —— 忽略大小写的比较
public class test {
public static void main(String[] args) {
String s1 = new String("abc");
String s2 = "Abc";
boolean flag1 = s1.equals(s2);
boolean flag2 = s1.equalsIgnoreCase(s2);
System.out.println(flag1); //false
System.out.println(flag2); //true
}
}
同理,键盘录入字符串比较时==也不行,所以以后要比较字符串的内容,就必须用String里面的方法
四、练习
1、
import java.util.Scanner;
public class test {
public static void main(String[] args) {
//已知正确的用户名和密码,模拟用户登录,三次机会,登录之后,给出相应提示
boolean flag = false;
for (int i = 0; i < 3; ) {
System.out.println("请输入用户名");
Scanner sc = new Scanner(System.in);
String name = sc.next();
System.out.println("请输入密码");
String pw = sc.next();
flag = panduan(name,pw);
if(flag){
System.out.println("登录成功");
break;
}
else{
i++;
System.out.println("登录失败,请重新登录");
}
}
if(!flag){
System.out.println("账户已被冻结,请联系管理员!!!");
}
}
public static boolean panduan(String name,String pw){
String user = "看月落月升";
String password = "123456789";
boolean flag1 = user.equals(name);
boolean flag2 = password.equals(pw);
if(flag1 && flag2) {
return true;
}
else{
return false;
}
}
}
2、
public class test {
public static void main(String[] args) {
///遍历输入的字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i); //根据索引找到该字符
System.out.println(c);
}
}
}
3、
import java.util.Scanner;
public class test {
public static void main(String[] args) {
///统计字符次数:大写字母,小写字母,数字字符
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next(); //这个方法不能获取空格,nextLine()可以,但两者不能混合使用\n影响
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(c >= 'a' && c <= 'z'){
smallCount++;
}
else if(c >= 'A' && c <= 'Z'){
bigCount++;
}
else if(c >= '0' && c <= '9'){
numberCount++;
}
}
System.out.println("小写字母有:"+smallCount+"个");
System.out.println("大写字母有:"+bigCount+"个");
System.out.println("数字字符有:"+numberCount+"个");
}
}
4、
import java.util.Scanner;
public class test {
public static void main(String[] args) {
//定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符返回
Scanner sc = new Scanner(System.in);
System.out.println("请输入数组个数");
int count = sc.nextInt();
int[] arr = new int[count];
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第"+(i+1)+"个数:");
int x = sc.nextInt();
arr[i] = x;
}
if(count == 0){
System.out.println("[]");
}
else{
System.out.printf("[");
for (int i = 0; i < arr.length; ) {
System.out.printf("%d",arr[i]);
if(i != arr.length - 1){
i++;
System.out.printf(",");
}
else{
System.out.printf("]");
break;
}
}
}
}
}
5、
import java.util.Scanner;
public class test {
public static void main(String[] args) {
//定义一个方法,实现字符串反转,键盘录入一个字符串,调用该方法,输出结果 abcd ——> dcba
Scanner sc = new Scanner(System.in);
System.out.println("请输入该字符:");
String str = sc.next();
String result = reverse(str);
System.out.println(result);
}
public static String reverse(String str) {
char[] demo = new char[str.length()];
int j = 0;
for (int i = str.length() - 1; i >= 0 ; i--,j++) {
char c = str.charAt(i);
demo[j] = c;
}
String result = new String(demo);
return result;
}
}
6、
public class test {
public static void main(String[] args) {
//手机号屏蔽 String substring(int beginindex,int endindex) 包左不包右
String phone = "19955558890";
String demo1 = phone.substring(0,3);
String demo2 = phone.substring(7,11);
String result = demo1 + "****" + demo2;
System.out.println(result);
}
}
7、
public class test {
public static void main(String[] args) {
//敏感词替换 String replace(旧值,新值);
String talk = "你玩得真好,以后不玩了,TMD,CNM";
String[] arr = {"TMD","CNM","SB","MLGB"};
for (int i = 0; i < arr.length; i++) {
talk = talk.replace(arr[i],"***");
}
System.out.println(talk);
}
}
五、StringBuilder的基本操作
StringBuilder是一个容器,创建后里面的内容是可以改变的,提高字符串的操作效率,节省内存
方法名 | 说明 |
---|---|
public StringBuilder() | 创建一个空白可变字符串对象,不含有任何内容 |
public StringBuilder(String str) | 根据字符串的内容,来创建可变字符串对象 |
StringBuilder sb = new StringBuilder();
常用方法
方法名 | 说明 |
---|---|
public StringBuilder(任意类型); | 添加数据,并返回对象本身 |
public StringBuilder reverse(); | 反转容器里的内容 |
public int length(); | 返回长度(字符出现的个数) |
public String toString(); | 通过toString()就可以把StringBulider转换为String |
public class test {
public static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder("你好");
//2.添加元素
// sb.append(1);
// sb.append(true);
// sb.append("abc");
//3.无需接收,直接转换
sb.reverse();
//获取长度
int len = sb.length();
System.out.println(len); //2
//打印:其是Java已经写好的类,打印对象是属性值,不是地址值
System.out.println(sb);
}
}
public class test {
public static void main(String[] args) {
//1.创建对象
StringBuilder sb = new StringBuilder();
//2.添加元素
sb.append("aaa");
sb.append("bbb");
sb.append("ccc");
System.out.println(sb);
//使其变为String
String str = sb.toString();
System.out.println(str.length());
}
}
六、链式编程
当我们再调用一个方法的时候,不需要用变量接收他的结果,可以继续调用其他方法
import java.util.Scanner;
public class test {
public static void main(String[] args) {
String str = getString().substring(1).replace("A","Q");
System.out.println(str);
}
public static String getString() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String str = sc.next();
return str;
}
}
综合练习
import java.util.Scanner;
public class test {
public static void main(String[] args) {
//对称字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String str = sc.next();
// char[] reverse = new char[str.length()];
// int j = str.length() - 1;
// for (int i = 0; i < str.length(); i++) {
// char c = str.charAt(i);
// reverse[j] = c;
// j--;
// }
// String result = new String(reverse);
String result = new StringBuilder().append(str).reverse().toString();
boolean b = result.equals(str);
if(b){
System.out.println("是对称字符串");
}else{
System.out.println("不是对称字符串");
}
}
}
七、StringJoiner
也可以看做成一个容器,创建之后内容可变
提高字符串的操作性效率,而且代码编写特别简洁
构造方法
方法名 | 说明 |
---|---|
public StringJoiner(间隔符号) | 创建一个StringJoiner对象,指定拼接的间隔符号 |
public StringJoiner(间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
成员方法
方法名 | 说明 |
---|---|
public StringJoiner add(添加的内容) | 添加数据,并返回对象本身 |
public int length() | 返回长度(字符出现的个数) |
public String toString() | 返回拼接后的字符串 |
import java.util.StringJoiner;
public class test {
public static void main(String[] args) {
/*//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//打印结果
System.out.println(sj); //aaa---bbb---cccc*/
StringJoiner sj = new StringJoiner(", ","[","]");
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length(); //包括添加的,[]和空格
System.out.println(len);
System.out.println(sj);
}
}
八、字符串原理
字符串存储的内存原理
直接赋值会复用字符串常量池里的
new出来的不会复用,而是开辟一个新的空间
==号比较的到底是什么?
基本数据类型比较数据值
引用数据类型比较地址值
字符串拼接的底层原理
字符串拼接的时候,如果有变量:
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接。
拼接后,再调用其toString方法转换为String类型,而toString方法的底层是直接new了一个字符串对象。
JDK8版本:系统会预估要字符串拼接之后的总大小,把要拼接的内容都放在数组中,此时也是产生一个新的字符串。
结论:
如果有很多字符串变量拼接,不要直接+。底层会创建多个对象,浪费时间和性能,使用StringBuilder和StringJoiner方法
字符串拼接的底层原理
如果没有变量参与,都是字符串直接相加,编译之后就是拼接之后的结果,会复用串池中的字符串。
如果有变量参与,每一行拼接的代码,都会在内存中创建新的字符串,浪费内存。
StringBuilder提高效率原理图
所有要拼接的内容都会往StringBuilder中放,不会创建很多无用的空间,节约内存
默认创建一个长度为16的字节数组
添加的内容长度小于16,直接存
添加的内容大于16会扩容(原来的容量*2+2)
如果扩容之后还不够,以实际长度为准
public class test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
System.out.println(sb.capacity()); //16
System.out.println(sb.length()); //0
sb.append("abcdefghijklmnopqrstuvwxyz0123456789");
System.out.println(sb.capacity()); //36
System.out.println(sb.length()); //36
}
}