1.API和API帮助文档
// API: (Application Programming Interface) 应用程序编程接口
// (简单理解: API就是别人已经写好的东西, 我们不需要自己编写, 直接使用即可)
public static void main(String[] args){
Random r = Random();
int number = r.nextInt(100);
}
// Java API: JDK中提供的各种功能的Java类, 这些类将底层的实现封装了起来, 能使用即可
// 已经学习的API
Scanner 键盘录入
Random 随机数1、打开API帮助文档
2、点击显示,找到索引下面的输入
3、再输入框中输入类名并点击显示
4、查看类所在的包
5、查看类的描述
6、查看构造方法
7、查看成员方法1.1 API文档练习
// 利用api帮助文档,使用Scanner类
// cat src/day10/src/com/yq/apidemo/ScannerDemo1.java
package com.yq.apidemo;
import java.util.Scanner;
public class ScannerDemo1 {
public static void main(String[] args){
//1.创建对象
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个小数");
//2.接受一个小数
double result = sc.nextDouble();
//3.打印输出
System.out.println(result);
}
}2.String类
2.1 String类概述
String 类代表字符串,Java 程序中的所有字符串文字(例如“abc”)都被实现为此类的实例。也就是说,Java 程序中所有的双引号字符串,都是 String 类的对象。
String 类在 java.lang 包下,所以使用的时候不需要导包!
2.2 String类的特点
字符串不可变,它们的值在创建后不能被更改
虽然 String 的值是不可变的,但是它们可以被共享
字符串效果上相当于字符数组( char[] ),但是底层原理是字节数组( byte[] )
2.3 创建String对象的两种方式
1)直接赋值
String name = 'abc'2)new方式
常用的构造方法
示例代码
// src/day10/src/com/yq/stringdemo/StringDemo1.java
package com.yq.stringdemo;
public class StringDemo1 {
public static void main(String[] args){
//1.直接赋值 获取一个字符串对象
String s1 = "abc";
System.out.println(s1); // abc
//2.使用new的方式 获取一个字符串对象
// 空参构造:可以获取一个空白的字符串对象
String s2 = new String();
System.out.println("@" + s2 + "!"); // @!
// 传递一个字符串,根据传递的字符串内容再创建一个新的字符串对象
String s3 = new String("abc");
System.out.println(s3); // abc
// 传递一个字符串数组,根据字符数组的内容,再创建一个新的字符串对象
// 需求:修改字符串的内容 abc --> Qbc
// abc --> {'a', 'b', 'c'} -- > {'Q', 'b', 'c'} --> "Qbc"
char[] chs = {'a', 'b', 'c', 'd'};
String s4 = new String(chs);
System.out.println(s4); // abcd
// 传递一个字节数组,根据字节数组的内容,再创建一个新字符串对象
// 应用场景:网络数据传输采用字节信息,需要进行字节信息转换
byte[] bytes = {97, 98, 99, 100}; // 根据ASCII对应
String s5 = new String(bytes);
System.out.println(s5);
}
}2.4 Java的内存模型
1) String直接赋值
使用 `StringTable(串池)`
注意:StringTable(串池) 在JDK7开始,从方法区中挪到了堆内存
当使用双引号直接赋值时,系统会检查该字符串在串池中是否存在(可节约内存空间)
不存在:创建新的
存在:复用2) new方式
每一次new都会在堆内存中创建一个新的内存空间,无论字符串是否已经存在
2.5 字符串的比较
2.5.1==号的作用
比较基本数据类型:比较的是具体的值
比较引用数据类型:比较的是对象地址值
2.5.2equals方法的作用
方法介绍
public boolean equals(String s) // 比较两个字符串内容是否相同、区分大小写 equalsIgnoreCase(String s) // 忽略大小写的比较
示例代码
// cat src/day10/src/com/yq/stringdemo/StringDemo2.java
package com.yq.stringdemo;
public class StringDemo2 {
public static void main(String[] args){
// 1.创建两个字符串对象
String s1 = new String("abc");
String s2 = "Abc";
// 2.==比较
// 基本数据类型:比的是数据值
// 引用数据类型:比的是地址值
System.out.println(s1 == s2); // false
// 3.比较字符串对象中的内容是否相等
boolean result1 = s1.equals(s2);
System.out.println(result1);
// 4.比较字符串对象中的内容是否相等(忽略大小写)
// 忽略大小写只能是英文状态下的,比如 a A
boolean result2 = s1.equalsIgnoreCase(s2);
System.out.println(result2);
}
}
// src/day10/src/com/yq/stringdemo/StringDemo3.java
package com.yq.stringdemo;
import java.util.Scanner;
public class StringDemo3 {
public static void main(String[] args){
// 1.使用键盘录入 abc
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str1 = sc.next();
// 2.代码中再顶一个字符串abc
String str2 = "abc";
// 3.用==比较
System.out.println(str1 == str2);
// 4.用equals比较
boolean result1 = str1.equals(str2);
System.out.println(result1);
// 4.用equals比较(忽略大小写)
boolean result2 = str2.equalsIgnoreCase(str2);
System.out.println(result2);
}
}2.6 用户登录案例
/*
需求: 已知正确的用户名和密码,请用程序实现模拟用户登录
总共给三次机会,登录之后,给出相应的提示
*/// cat src/day10/src/com/yq/stringdemo/StringDemo4.java
package com.yq.stringdemo;
import java.util.Scanner;
public class StringDemo4 {
public static void main(String[] args){
//1.定义两个变量,记录正确的用户名、密码
String rightUsername = "zhangsan";
String rightPassword = "123456";
for(int i = 0; i < 3; i++){
//2.键盘录入用户名、密码
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名");
String username = sc.next();
System.out.println("请输入密码");
String password = sc.next();
//3.比较
if (username.equals(rightUsername) && password.equals(rightPassword) ){
System.out.println("用户登录成功");
break;
} else {
if (i == 2){
//如果尝试次数为3,仍然登录失败,则提示账号锁定
System.out.println("尝试次数过多,"+ username + "已被锁定,请联系管理员");
} else {
System.out.println("用户登录失败,用户名或密码有误,您还剩下"+ (2- i) + "次机会");
}
}
}
}
}2.7遍历字符串案例
// 需求:键盘录入一个字符串,使用程序实现:在控制台遍历该字符串
public char charAt(int index): 根据索引返回字符
public int length(): 返回此字符串的长度
数组的长度:数组名.length
字符串的长度:字符串对象.length()// cat src/day10/src/com/yq/stringdemo/StringDemo5.java
package com.yq.stringdemo;
import java.util.Scanner;
public class StringDemo5 {
public static void main(String[] args){
// 1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
// 2.进行遍历
for (int i = 0; i < str.length(); i++) {
// i 一次表示字符串的每一个索引
//索引的范围:0 ~ 长度-1
//根据索引获取字符串里面的每一个字符
//ctrl + alt + V 自动生成左边的接受变量
char c = str.charAt(i);
System.out.println(c);
}
}
}2.8 统计字符次数案例
// 键盘录入一个字符串,统计该字符串中大写字母字符,小写字母字符,数字字符出现的次数(不考虑其他字符)// cat src/day10/src/com/yq/stringdemo/StringDemo6.java
package com.yq.stringdemo;
import java.util.Scanner;
public class StringDemo6 {
public static void main(String[] args) {
// 1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
// 2.统计字符串(小写字母、大写字母、数字的个数) 三个计数器
int bigCount = 0;
int smallCount = 0;
int numberCount = 0;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
//System.out.println(c);
if (c >= 'a' && c <= 'z'){
// char类型的遍历在参与计算的时候,会自动类型提升为int,查询ASCII表
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);
}
}2.9 字符串拼接案例
定义一个方法,把 int 数组中的数据按照指定的格式拼接成一个字符串返回,
调用该方法,并在控制台输出结果。
例如,
数组为 int[] arr = {1,2,3};
执行方法后的输出结果为:[1, 2, 3]// cat src/day10/src/com/yq/stringdemo/StringDemo7.java
package com.yq.stringdemo;
public class StringDemo7 {
public static void main(String[] args) {
int[] arr = new int[]{1, 2, 3};
String str = arrToString(arr);
System.out.println(str);
}
//要做什么? 遍历数组,并将数组拼接为一个字符串
//需要什么? 需要数组
//是否需要返回? 需要返回一个拼接后的字符串
public static String arrToString(int[] arr){
if(arr == null){
return "";
}
if (arr.length == 0){
return "[]";
}
//若数组不为空、长度不为0(数组中有内容)
String result = "[";
for (int i = 0; i < arr.length; i++) {
// i索引 arr[i]元素
if (i == arr.length - 1){
result = result + arr[i] ;
} else {
result = result + arr[i] + ", ";
}
}
result = result + "]";
return result;
}
}2.10 字符串反转
定义一个方法,实现字符串反转
键盘录入一个字符串,调用方法后,在控制台输出结果
例如,键盘录入abc,输出结果cba// src/day10/src/com/yq/stringdemo/StringDemo8.java
package com.yq.stringdemo;
public class StringDemo8 {
public static void main(String[] args) {
String result = reverser("abc");
System.out.println(result);
}
//1.要做什么 ==》字符串的反转
//2.需要什么 ==》需要一个字符串
//3.是否需要返回结果 ==》 需要
public static String reverser(String str){
String result = "";
for (int i = str.length() - 1; i >= 0; i--) {
// i 一次表示字符串中每一个索引(倒序)
char c = str.charAt(i);
result = result + c;
}
return result;
}
}2.11 金额转换
把2135变成:零佰零拾零万贰仟壹佰叁拾伍元
把789变成:零佰零拾零万零仟柒佰捌拾玖元// src/day10/src/com/yq/stringdemo/StringDemo9.java
package com.yq.stringdemo;
import java.util.Scanner;
public class StringDemo9 {
public static void main(String[] args){
//1.键盘录入一个金额
Scanner sc = new Scanner(System.in);
int money;
while (true){
System.out.println("请输入一个金额");
money = sc.nextInt();
if (money >= 0 && money <= 9999999) {
break;
} else{
System.out.println("金额无效");
}
}
String moneyStr = ""; //定义一个遍历用来表示钱的大写
//2.得到money中的每一位数组
while (true){
//从右往左获取数据,因为右侧是数据的各位
int ge = money % 10;
String capitalNumber = getCapitalNumber(ge);
moneyStr = capitalNumber + moneyStr; //拼接
money = money / 10;
//如果数字上的每一位全部获取,那么money记录的就是0,此时循环结束
if (money == 0){
break;
}
}
//3.在前面补零,补齐七位
int count = 7 - moneyStr.length();
for (int i = 0; i < count; i++){
moneyStr = "零" + moneyStr;
}
System.out.println(moneyStr);
//4.插入单位
//定义数组表示单位
String[] arr = {"佰", "拾", "万", "仟", "佰", "拾", "元"};
String result = "";
//遍历moneyStr ,将arr的单位插入
for (int i = 0; i < moneyStr.length(); i++){
char c = moneyStr.charAt(i);
result = result + c + arr[i]; //拼接
}
System.out.println(result);
}
//定义一个方法将数字变成大写的中文
public static String getCapitalNumber(int number){
//定义数组,让数字跟大写的中文产生一个对应关系
String[] arr = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
return arr[number];
}
}2.12 手机号部分屏蔽
需求:以字符串的形式从键盘接受一个手机号,将中间四位号码屏蔽
最终效果为:`131****9468`// src/day10/src/com/yq/stringdemo/StringDemo10.java
package com.yq.stringdemo;
public class StringDemo10{
public static void main(String[] args){
//1.获取一个手机号码
String phoneNumber = "13112345678";
//2.截取手机号码前三位
String start = phoneNumber.substring(0,3);
//Systeme.out.println(start);
//3.截取手机号后四位
String end = phoneNumber.substring(7);
//4.拼接
String result = start + "****" + end;
System.out.println(result);
}
}2.13 身份证信息查看
身份证的每一位都是有固定的含义:
* 1、2位:省份
* 3、4位:城市
* 5、6位:区县
* 7-14位:出生年、月、日
* 15、16位:所在地派出所
* 17位:性别(奇数男性,偶数女性)
* 18位:个人信息码(随机产生)
要求打印内容方式如下:
人物信息为:
出生年月日:XXXX年X月X日
性别为:男/女// src/day10/src/com/yq/stringdemo/StringDemo11.java
package com.yq.stringdemo;
public class StringDemo11 {
public static void main(String[] args){
//1.定义一个字符串记录身份证号码
String id = "321281202001011234";
//2.获取出生年月日
String year = id.substring(6,10);
String month = id.substring(10,12);
String day = id.substring(12,14);
System.out.println("人物信息为: ");
System.out.println("出生年月日: " + year + "年" + month + "月" + day + "日" );
//3.获取性别
char gender = id.charAt(16);
//利用ASCII码表进行转换
//'0' ---> 48
//'1' ---> 49
//'2' ---> 50
//'3' ---> 51
//'4' ---> 52
//'5' ---> 53
//'6' ---> 54
//'7' ---> 55
//'8' ---> 56
//'9' ---> 57
int num = gender - 48; //字符转整型( -48)
if (num % 2 == 0){
System.out.println("性别为: 女");
} else {
System.out.println("性别为: 男");
}
}
}2.14 敏感词替换
字符串中包含(TMD),则使用***替换package com.yq.stringdemo;
public class StringDemo12 {
public static void main(String[] args){
//1.获取到说的话
String talk = "你玩的真好,以后不要再玩了, TMD , CNM";
//2.定义敏感词库
String[] arr = {"TMD", "CNM", "SB", "MLGB"};
//3.循环获取每一个敏感词,依次进行替换
for (int i = 0; i < arr.length; i++){
talk = talk.replace(arr[i], "***");
}
//4.打印
System.out.println(talk);
}
}3.StringBuilder
StringBuilder可以看成是一个容器,创建之后里面的内容是可变的
作用:提高字符串的操作效率
构造方法:
public StringBuilder() //创建一个空白可变字符串对象,不含有任何内容
public StringBuilder(String str) //根据字符串的内容,创建可变字符串对象
StringBuilder sb = new StringBuilder("abc");
成员方法:
public StringBuilder append(任意类型) //添加数据,并返回对象本身
public StringBuilder reverse() //反转容器中的内容
public int length() //返回长度(字符出现的个数)
public String toString() //通过toString()就可以实现把StringBuilder转换为Stringpackage com.yq.stringbuilderdemo;
public class StringBuilderDemo3 {
public static void main(String[] args){
//1.创建对象
StringBuilder sb = new StringBuilder("abc");
//2.添加元素
sb.append(1);
sb.append(2.3);
sb.append(true);
//反转
sb.reverse();
//获取长度
int len = sb.length();
System.out.println(len);
/* 拓展:
因为StringBuilder是Java已经写好的类,Java在地层对他做了一些特殊处理,打印的对象不是地址值而是属性值
*/
System.out.println(sb);
System.out.println(sb.reverse()); //输出反转后的内容
}
}package com.yq.stringbuilderdemo;
public class StringBuilderDemo4 {
public static void main(String[] args){
//1.创建对象
StringBuilder sb = new StringBuilder();
//2.添加字符串
/*
sb.append("aaa");
sb.append("bbb");
sb.append("ccc");
sb.append("ddd");
*/
//链式写法:
sb.append("aaa").append("bbb").append("ccc").append("ddd");
System.out.println(sb);
//3.将StringBuilder变回字符串
String str = sb.toString();
System.out.println(str);
}
}package com.yq.stringbuilderdemo;
import java.util.Scanner;
public class StringBuilderDemo5{
public static void main(String[] args){
/* 链式编程:
当我们在调用一个方法时,不需要用遍历接受他的结果,可以继续调用其他的方法
*/
int len = getString().substring(1).replace("A", "Q").length();
System.out.println(len);
}
public static String getString(){
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串");
String str = sc.next();
return str;
}
}3.1 对称字符串
需求:键盘接受一个字符串,程序判断出该字符串是否为对称字符串,并在控制台打印是或者不是
对称字符串: 12321 111
非对称字符串: 123123package com.yq.stringbuilderdemo;
import java.util.Scanner;
public class StringBuilderDemo6 {
/* 拓展:使用StringBuilder的场景
1.字符串的拼接
2.字符串的反转
*/
public static void main(String[] args){
//1.键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串: ");
String str = sc.next();
//2.反转键盘录入的字符串
String result = new StringBuilder().append(str).reverse().toString();
//3.比较
if (str.equals(result)){
System.out.println("当前字符串是对称字符串");
} else {
System.out.println("当前字符串不是对称字符串");
}
}
}3.2 拼接字符串
需求: 定义一个方法,把int数组中的数据按照指定的格式拼接成一个字符串返回
调用该方法, 并在控制台输出结果
例如: 数组为 int[] arr = {1, 2, 3};
执行方法后的输出结果为: [1, 2, 3]package com.yq.stringbuidlerdemo;
public class StringBuilderDemo7{
public static void main(String[] args){
//1.定义数组
int[] arr = {1, 2, 3};
//2.调用方法把数组变成字符串
String str = arrToString(arr);
System.out.println(str);
}
public static String arrToString(int[] arr){
StringBuilder sb = new StringBuilder();
sb.append("[");
for (int i = 0; i < arr.length ; i++){
if (i == arr.length - 1){
sb.append(arr[i]);
} else {
sb.append(arr[i]).append(", ");
}
}
sb.append("]");
return sb.toString();
}
}4.StringJoiner
StringJoiner与StringBuilder一样,也可以看出是一个容器,创建之后里面的内容是可变的
作用: 提高字符串的操作效率,而且代码编写特别简洁
JDK8才出现
StringJoiner的构造方法:
public StringJoner(间隔符合) //创建一个StringJoiner对象,指定拼接时的间隔符号
public StringJoiner(间隔符号, 开始符号, 结束符号) //创建一个StringJoiner对象,指定拼接的间隔符号、开始符号、结束符号
StringJoiner的成员方法:
public StringJoiner add(添加的内容) //添加数据
public int length() //返回容器的长度
public String toString() //返回为字符串package com.yq.stringjoinerdemo;
import java.util.StringJoiner;
public class StringJoinerDemo1 {
public static void main(String[] args){
//1.创建一个对象,并指定中间的间隔符号
StringJoiner sj = new StringJoiner("---");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
//3.打印结果
System.out.println(sj);
}
}package com.yq.stringjoinerdemo;
import java.util.StringJoiner;
public class StringJoinerDemo2{
public static void main(String[] args){
//1.创建对象
StringJoiner sj = new StringJoiner(", ", "[", "]");
//2.添加元素
sj.add("aaa").add("bbb").add("ccc");
int len = sj.length();
System.out.println(len);
//3.打印
System.out.println(sj);
String str = sj.toString();
System.out.println(str);
}
}5 字符串原理
底层原理1: 字符串存储的内存原理
直接赋值,会复用字符串常量池中的
new出来不会复用,而是开辟一个新的空间
底层原理2: ==号比较的是什么
基本数据类型,比较数据值
引用数据类型,比较地址值
底层原理3:字符串拼接的底层原理
1).等号右边,没有变量参与,都是字符串
触发字符串的优化机制,在编译的时候就已经是最终的结果了(会复用串池中的字符串)
2).等号右边,有变量参与,会创建新的字符串,浪费内存
(一个加号,堆内存中至少会有俩对象StringBuilder、toString)
JDK8字符串拼接的底层原理
虽然字符串拼接时,会进行预估,但这个预估过程也会有消耗,浪费时间

底层原理4:StringBuilder提高效率原理图
注意:StringBuilder是一个内容可变的容器
所有要拼接的内容都会往一个StringBuilder中放,不会创建很多无用的空间,节约内存
StringBuilder不会被撑爆
常见面试题:
1.下面代码运行结果?
public class Test3{
public static void main(String[] args){
String s1 = "abc"; //记录串池中的地址值
String s2 = "ab";
String s3 = s2 + c; //新new出来的对象
System.out.println(s1 == s3); //false
}
}
字符串拼接的时候,如果有变量:
JDK8以前:系统底层会自动创建一个StringBuilder对象,然后再调用其append方法完成拼接,拼接后,再调用其toString转换为String类型,而toString方法的底层是直接new了一个新的字符串对象
JDK8版本:系统会预估字符串拼接后的总大小,把需要拼接的内容放在数组中,此时也会产生一个新的字符串(new出一个新对象)
2.下面代码运行结果?
public class Test4{
public static void main(String[] args){
String s1 = "abc"; //记录串池中的地址值
String s2 = "a" + "b" + "c"; //没有变量,服用串池中的字符串
System.out.println(s1 == s2); //ture
}
}
在编译的时候,就会将"a" + "b" + "c"拼接为"abc"底层原理5:StringBuilder源码分析
默认创建一个长度为16的字节数组
添加的内容长度小于16,直接存
添加的内容大于16会扩容(原来容量*2+2)
如果扩容之后还不够,以实际长度为准(需要多少扩容多少)package com.yq.test;
public class Test4 {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
//容量,最多装多少
//长度,已经装了多少
System.out.println(sb.capacity()); //16
System.out.println(sb.length()); //0
sb.append("abc");
System.out.println(sb.capacity()); //16
System.out.println(sb.length()); //3
StringBuilder sb1 = new StringBuilder();
sb1.append("abcdefghijklmnopqrstuvwxyz");
System.out.println(sb1.capacity()); //16*2+2=34
System.out.println(sb1.length()); //26
StringBuilder sb2 = new StringBuilder();
sb2.append("abcdefghijklmnopqrstuvwxyz0123456789");
System.out.println(sb2.capacity()); //36,需要多少扩成多少
System.out.println(sb2.length()); //36
}
}
评论区