Java基础教程-06-常用API
1. API简介
1.1 概述
• API全称是Application Programming Interface(应用程序编程接口). 例如:
编写一个机器人程序去控制机器人踢足球,程序就需要向机器人发出向前跑、向后跑、射门、抢球等各种命令,机器人厂商一定会提供一些用于控制机器人的接口类,这些类中定义好了操作机器人各种动作的方法。其实,这些接口类就是机器人厂商提供给应用程序编程的接口,大家把这些类称为API。
• Java API: 指的就是JDK中提供的各种功能的Java类.
这些类将底层的实现封装了起来, 我们不需要关心这些类是如何实现的, 只需要学习这些类如何使用即可.
我们可以通过帮助文档来学习这些API如何使用.
记忆:
- API本意指的是JDK中提供的各种功能的Java类.
- 但实际开发中, 我们常说的打开API指的不是JDK提供的Java类, 而是API 帮助文档.
- API 帮助文档就相当于说明书, 是用来介绍JDK提供的各个接口类的功能的, 从而帮助我们快速上手使用.
1.2 帮助文档的使用步骤
- 右键打开该文档.
- 找到索引选项卡中的输入框.
- 在输入框中输入要查找的类, 例如Random.
4. 看类在哪个包下. 如果是java.lang包下的类, 则无需导包, 可以直接使用.
而其他包下的类和接口, 在使用前必须先导包.
5. 大概的看下类的说明, 知道该类是用来干嘛的即可.
6. 看构造方法, 根据指定的参数列表, 创建该类的对象.
7. 看成员方法, 重点看(返回值, 方法名, 参数列表, 方法描述)
2. Object类
2.1 概述
Object类是所有类的父类, 所有的类都直接或者间接继承自Object类.
2.2 构造方法
public Object() //Object类中只有一个空参构造.
思考题: 回想咱们之前说过的一句话为什么子类的构造方法的第一行, 默认都是super(), 而不是带参构造呢?
2.3 成员方法
• public String toString();
解释: 返回对象的字符串表示形式(即: 地址值), 无意义, 建议子类重写该方法.
• public boolean equals(Object obj);
解释: 比较两个对象是否相等, 默认比较的是地址值, 无意义, 子类一般都会重写该方法.
注意: 实际开发中, 我们认为如果同一个类的两个对象, 各个属性值都相同, 那么它们就是同一个对象.
例如:
//虽然s1和s2对象的地址值不同, 但是它们的属性值都相同, 所以实际开发中我们认为它们是同一个对象.
Student s1 = new Student("刘亦菲", 33);
Student s2 = new Student("刘亦菲", 33);
2.4 示例一: toString方法演示
需求
- 定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
- 在StudentTest测试类中, 创建学生类对象并直接打印, 观察程序的运行结果.
参考代码:
学生类:
//JavaBean类, 表示学生.
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
//重写Object类的equals()方法, 改为比较: 对象的各个属性值.
@Override
public boolean equals(Object o) { //s1.equals(s2)
/*
s1: this
s2: o student
*/
//1. 提高效率, 有可能要比较的两个对象是同一个类型的对象.
if (this == o) {
return true;
}
//2. 提高健壮性, 有可能要比较的两个对象不是同一个类型的对象.
if (o == null || this.getClass() != o.getClass()) {
return false;
}
//3. 向下转型
Student student = (Student) o;
//4. 比较两个对象的年龄是否相同.
if (this.age != student.age) {
return false;
}
//5. 比较两个对象的姓名是否相同.
//这里的equals()指的是: String类中的equals()方法
return this.name != null ? this.name.equals(student.name) : student.name == null;
}
@Override
public String toString() {
/*return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';*/
//自定义toString()方法的内容
return name + "..." + age;
}
}
测试类:
public class StudentDemo01 {
public static void main(String[] args) {
Student s = new Student("刘亦菲", 33);
System.out.println(s.toString());
System.out.println(s);
}
}
运行结果为:
刘亦菲...33
刘亦菲...33
2.5 示例二: equals()方法演示
需求
- 定义学生类Student, 属性为姓名和年龄, 生成对应的空参, 全参, getXxx()和setXxx()方法.
- 在StudentTest测试类中, 创建两个学生类对象, 属性值都是: 刘亦菲, 33
- 并直接打印, 观察程序的运行结果.
参考代码
public class StudentDemo02 {
public static void main(String[] args) {
Student s1 = new Student("刘亦菲", 33);
Student s2 = new Student("刘亦菲", 33);
//比较: 引用类型.
System.out.println(s1 == s2); //false, 比较地址值.
System.out.println(s1.equals(s2)); //true, 重写后, 比较的是: 对象的属性值.
System.out.println("-----------------");
//比较: 基本类型
System.out.println(10 == 20); //比较的是: 数值
//System.out.println(10.equals(10)); //这样写会报错.
}
}
运行结果为:
false
true
-----------------
false
3. String类
3.1 概述
String代表字符串类, 即: 由多个字符组成的一串数据. 字符串的本质就是一个字符数组.
3.2 构造方法
• public String()
解释: 创建一个空白字符串对象, 不包含任何内容.
• public String(String s)
解释: 把字符串数据封装成字符串对象.
• public String(char[] value)
解释: 把字符数组的数据封装成字符串对象.
• public String(char[] value, int index, int count)
解释: 把字符数组的一部分数据封装成字符串对象.
• public String(byte[] bys)
解释: 把字节数组的数据封装成字符串对象.
• public String(byte[] bys, int index, int count)
解释: 把字节数组的一部分数据封装成字符串对象.
3.3 示例一: 创建字符串对象
需求
- 分别通过上述的三种方式创建字符串对象.
- 在main方法中, 通过输出语句, 直接打印创建好的字符串对象.
提示: 输出语句直接打印对象, 默认调用了对象的toString()方法.
参考代码
public class StringDemo01 {
public static void main(String[] args) {
//1. 演示 public String(); 通过空参构造, 创建字符串对象.
String s1 = new String();
System.out.println("s1: " + s1); //输出的不是地址值, 说明String重写了Object#toString().
System.out.println("-------------------");
//2. 演示 public String(String s); 通过带参构造, 创建字符串对象.
String s2 = new String("abc");
System.out.println("s2: " + s2);
System.out.println("-------------------");
//3. 演示 public String(char[] chs); 把接收到的字符数组, 转成其对应的字符串形式.
char[] chs = {'h', 'e', '黑','马','程','序','员', 'l', 'l', 'o'};
String s3 = new String(chs);
System.out.println("s3: " + s3);
System.out.println("-------------------");
//4. 演示public String(char[] chs, int index, int count); 把接收到的字符数组的一部分, 转成其对应的字符串形式.
String s4 = new String(chs, 2, 5);
System.out.println("s4: " + s4);
System.out.println("-------------------");
//5. 演示public String(byte[] bys); 把接收到的字节数组, 转成其对应的字符串形式.
byte[] bys = {97, 98, 99, 65, 66};
String s5 = new String(bys);
System.out.println("s5: " + s5); //abcAB
System.out.println("-------------------");
//6. 演示public String(byte[] bys, int index, int count); 把接收到的字节数组的一部分, 转成其对应的字符串形式.
String s6 = new String(bys, 1, 2);
System.out.println("s6: " + s6);
System.out.println("-------------------");
//7. 实际开发写法
String s7 = "abc"; //语法糖.
System.out.println("s7: " + s7);
}
}
运行结果为:
s1:
-------------------
s2: abc
-------------------
s3: he黑马程序员llo
-------------------
s4: 黑马程序员
-------------------
s5: abcAB
-------------------
s6: bc
-------------------
s7: abc
记忆: 最常用的创建字符串对象的方法是: String s = “abc”;
3.4 String创建对象的特点
3.4.1 创建字符串对象的方式
- 通过new创建的字符串对象, 每一次new都会申请一个内存空间, 虽然内容相同, 但是地址值不同.
char[] chs = {'a', 'b', 'c'};
String s1 = new String(chs);
String s2 = new String(chs); //这里的s1和s2的地址值肯定是不同的.
- 通过""方式创建的字符串, 只要字符序列相同(顺序和大小写), 无论在程序代码中出现几次, JVM都只会创建一个String对象, 并在字符串池中维护.
String s1 = "abc";
String s2 = "abc"; //这两个对象在内存中其实是同一个对象.
3.4.2 示例
需求
- 定义字符数组chs, 初始化值为: 'a, ‘b’, ‘c’, 这三个字符 .
- 将其分别封装成s1, s2这两个字符串对象.
- 通过==判断s1和s2这两个字符串对象是否相同.
- 直接通过""的方式创建两个字符串对象s3和s4.
- 通过==判断s3和s4这两个字符串对象是否相同.
参考代码
public class StringDemo02 {
public static void main(String[] args) {
//1.定义字符数组chs, 初始化值为: 'a, 'b', 'c', 这三个字符 .
char[] chs = {'a', 'b', 'c'};
//2.将其分别封装成s1, s2这两个字符串对象.
String s1 = new String(chs);
String s2 = new String(chs);
//3.通过==判断s1和s2这两个字符串对象是否相同.
System.out.println(s1 == s2); //false
System.out.println("-----------------------------------");
//4.直接通过""的方式创建两个字符串对象s3和s4.
String s3 = "abc";
String s4 = "abc";
//5.通过==判断s3和s4这两个字符串对象是否相同.
System.out.println(s3 == s4); //true
System.out.println(s3 == s1); //false
}
}
运行结果为:
false
-----------------------------------
true
false
内存图解:
3.5 字符串的比较
3.5.1 涉及到的方法
• public boolean equals(Object obj)
解释: 比较两个字符串的内容是否相同, 区分大小写. 即: “a” 和 "A"不是同一个字符串.
• public boolean equalsIgnoreCase(String s)
解释: 比较两个字符串的内容是否相同, 不区分大小写. 即: “a” 和 "A"是同一个字符串.
3.5.2 示例演示
需求
- 定义字符数组chs, 初始化值为: 'a, ‘b’, ‘c’, 这三个字符 .
- 将其分别封装成s1, s2这两个字符串对象.
- 直接通过""的方式创建两个字符串对象s3和s4.
- 通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
- 通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
- 通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
参考代码
public class StringDemo03 {
public static void main(String[] args) {
//1.定义字符数组chs, 初始化值为: 'a, 'b', 'c', 这三个字符 .
char[] chs = {'a', 'b', 'c'};
//2.将其分别封装成s1, s2这两个字符串对象.
String s1 = new String(chs);
String s2 = new String(chs);
//3.直接通过""的方式创建两个字符串对象s3和s4.
String s3 = "abc";
String s4 = "aBc";
//4.通过==分别判断s1和s2, s1和s3, s3和s4是否相同.
System.out.println(s1 == s2); //false
System.out.println(s2 == s3); //false
System.out.println(s3 == s4); //false
System.out.println("-------------------");
//5.通过equals()分别判断s1和s2, s1和s3, s3和s4是否相同.
System.out.println(s1.equals(s2)); //true
System.out.println(s1.equals(s3)); //true
System.out.println(s3.equals(s4)); //false
System.out.println("-------------------");
//6.通过equalsIgnoreCase()判断字符串abc和ABC是否相同.
System.out.println(s3.equalsIgnoreCase("ABC")); //true
}
}
运行结果为:
false
false
false
-------------------
true
true
false
-------------------
true
3.6 示例二: 模拟用户登录
3.6.1 需求
- 模拟用户登录, 只给3次机会, 登录成功则提示"欢迎您, ***".
- 登录失败则判断是否还有登录机会, 有则提示剩余登录次数, 没有则提示"您的账号已被锁定".
- 假设初始化账号和密码分别为: “传智播客”, “黑马程序员”.
3.6.2 参考代码
import java.util.Scanner;
//案例: 模拟用户登录, Scanner, String, if.else <=> 三元, for循环
public class Demo01 {
public static void main(String[] args) {
/*
需求:
1.模拟用户登录, 只给3次机会, 登录成功则提示"欢迎您, ***".
2.登录失败则判断是否还有登录机会, 有则提示剩余登录次数, 没有则提示"您的账号已被锁定".
3.假设初始化账号和密码分别为: "传智播客", "黑马程序员".
*/
//1. 创建键盘录入对象.
Scanner sc = new Scanner(System.in);
//2. 设定初始账号和密码.
String username = "传智播客";
String password = "黑马程序员";
//3. 因为只给3次机会, 所以用for循环.
for (int i = 0; i < 3; i++) {
//4. 提示用户录入账号和密码, 并接收.
System.out.println("请录入您的账号: ");
String uname = sc.nextLine();
System.out.println("请录入您的密码: ");
String pw = sc.nextLine();
//5. 判断用户录入的账号和密码是否正确.
//5.1 如果正确, 提示登录成功, 然后循环结束.
if (username.equals(uname) && password.equals(pw)) {
//System.out.println("登陆成功!");
System.out.println("欢迎您, " + uname);
break; //细节.
} else {
//5.2 如果错误, 判断是否还有登陆机会.
//5.2.1 如果有, 则提示: 登陆失败, 你还有*次机会.
if (i != 2) {
System.out.println("登陆失败, 你还有" + (2 - i) + "次机会.");
} else {
//5.2.2 如果没有, 提示: 账号锁定.
System.out.println("账号被锁定, 请于管理员联系 110");
}
}
}
}
}
3.7 示例三: 遍历字符串
需求
键盘录入一个字符串, 使用程序实现在控制台遍历打印该字符串.
提示
• public int length()
解释: 获取字符串的长度.
• public char charAt(int index)
解释: 根据索引, 获取该索引对应的字符.
参考代码
import java.util.Scanner;
public class Demo02 {
public static void main(String[] args) {
String str = "abc";
//1. 演示length方法
System.out.println("length方法: " + str.length()); //3
//2. 演示charAt()方法.
System.out.println("charAt方法: " + str.charAt(2)); //c
//StringIndexOutOfBoundsException: 字符串索引越界异常.
//System.out.println("charAt方法: " + str.charAt(20)); //报错
//需求: 键盘录入一个字符串, 使用程序实现在控制台遍历打印该字符串.
//1. 创建键盘录入对象.
Scanner sc = new Scanner(System.in);
//2. 提示用户录入并接收字符串.
System.out.println("请录入一个字符串: ");
String s = sc.nextLine();
//3. 通过for循环, 遍历字符串, 获取字符串中的每一个索引值.
for (int i = 0; i < s.length(); i++) {
//i就是字符串中, 每个字符的索引
//4. 根据索引, 获取到字符串中的每一个字符.
char ch = s.charAt(i);
//5. 打印结果.
System.out.println(ch);
}
}
}
运行结果为:
length方法: 3
charAt方法: c
请录入一个字符串:
I LOVE luokk.
I
L
O
V
E
l
u
o
k
k
.
3.8 示例四: 统计字符次数
需求
键盘录入一个字符串, 统计该字符串中大写字母字符, 小写字母字符, 数字字符出现的次数.
注意: 不考虑其他字符, 例如@, !, , /等
参考代码
import java.util.Scanner;
//案例: 统计各类型字符的次数
public class Demo03 {
public static void main(String[] args) {
/*
需求:
键盘录入一个字符串, 统计该字符串中大写字母字符, 小写字母字符, 数字字符出现的次数.
注意: 不考虑其他字符, 例如@, !, \, /等
*/
//1. 提示用户录入并接收.
Scanner sc = new Scanner(System.in);
System.out.println("请录入一个字符串: ");
String str = sc.nextLine();
//2. 定义三个int类型的变量, 分别表示: 大写字母字符, 小写字母字符, 以及数字字符的次数.
int bigCount = 0, smallCount = 0, numberCount = 0;
//3. 通过for循环, 遍历字符串, 获取到每一个字符.
for (int i = 0; i < str.length(); i++) {
//获取到每一个字符
char ch = str.charAt(i);
//4. 判断当前遍历到的字符属于哪种字符, 是哪种, 对应的计数器就++
if (ch >= 'A' && ch <= 'Z') {
//大写字母字符
bigCount++;
} else if(ch >= 'a' && ch <= 'z') {
//小写字母字符
smallCount++;
} else if(ch >= '0' && ch <= '9') {
//数字字符
numberCount++;
}
}
//5. 循环结束后, 打印各个计数器的值即可.
System.out.println("大写字母字符的个数: " + bigCount);
System.out.println("小写字母字符的个数: " + smallCount);
System.out.println("数字字符的个数: " + numberCount);
}
}
运行结果为:
I love luokk. I LIVE IN CHINA.
大写字母字符的个数: 13
小写字母字符的个数: 9
数字字符的个数: 0
3.9 案例五: 字符串拼接
需求
- 定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
- 在main方法中, 调用上述的方法.
- 例如: 数组为int[] arr = {1, 2, 3}, 则拼接后, 结果为: [1, 2, 3]
参考代码
public class Demo04 {
public static void main(String[] args) {
//演示concat()方法, 了解即可, 实际开发写的比较少.
String s1 = "ab";
String s2 = "c";
String s3 = s1 + s2; //s3 = "abc", 会开辟空间(堆)
String s4 = s1.concat(s2); //s4 = "abc", 不会开辟堆空间.
System.out.println("s3: " + s3);
System.out.println("s4: " + s4);
System.out.println("--------------------");
//2. 调用方法
//int[] arr = {1, 2, 3};
int[] arr = null;
System.out.println(array2String(arr));
}
//1. 定义方法arrayToString(), 把int数组的元素按照指定的格式拼接成一个字符串, 并返回.
public static String array2String(int[] arr) {
//先做越界处理.
if (arr == null || arr.length == 0) {
return "[]";
}
//正常的拼接逻辑.
String s = "[";
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
s += (arr[i] + "]");
} else {
s += (arr[i] + ", ");
}
//通过三元优化,自己写.
}
return s;
}
}
运行结果为:
s3: abc
s4: abc
--------------------
[]
3.10 案例六: 字符串反转
需求
- 定义方法reverse(), 实现字符串的反转.
- 在main方法中键盘录入一个字符串, 调用上述的方法后, 在控制台输出结果.
- 例如: 键盘录入abc, 输出结果cba.
提示: 用for循环, 倒序遍历数组, 然后拼接每一个元素即可.
参考代码
import java.util.Scanner;
//案例: 演示字符串反转.
public class Demo05 {
public static void main(String[] args) {
//2. 提示用户录入字符串, 并接收.
Scanner sc = new Scanner(System.in);
System.out.println("请录入一个字符串: ");
String str = sc.nextLine();
//3. 调用方法.
System.out.println(reverse(str));
}
//1. 定义方法reverse(), 实现字符串的反转. 思路: 就是倒序输出字符串, 然后拼接即可.
public static String reverse(String s) {
//1.1 定义字符串, 记录反转后的结果.
String newStr = "";
//1.2 遍历原始字符串, 然后倒序输出.
for (int i = s.length() - 1; i >= 0; i--) {
//1.3 拼接结果.
newStr += s.charAt(i);
}
//1.4 返回具体的结果.
return newStr;
}
}
运行结果为:
请录入一个字符串:
I love luokk
kkoul evol I
3.11 通过帮助文档查看String中的方法
• public boolean equals(Object obj)
解释: 比较两个字符串的内容是否相同, 区分大小写.
• public char charAt(int index)
解释: 根据给定的索引, 获取其对应的字符.
• public int length()
解释: 获取字符串的长度.
4. StringBuilder类
分析如下代码, 执行效率是高还是低呢?
String s = "hello";
s += "world";
System.out.println(s);
解释:
如果字符串进行拼接操作, 每次拼接, 都会构建一个新的String对象, 即耗时, 又浪费内存空间. 而这种操作还不可避免,.那有没有一种比较好的方式来解决这个问题呢?
答案是肯定的, 我们可以通过Java提供的StringBuilder类来解决这个问题.
4.1 概述
• StringBuilder类在java.lang包下, 无需导包, 可以直接使用.
• StringBuilder是一个可变的字符序列, 也叫字符串缓冲区类.
• 我们可以把它看做一个容器, 这里的可变指的是StringBuilder对象中的内容是可变的
String和StringBuilder之间的区别
• String: 内容是不可变的.
• StringBuilder: 内容是可变的.
4.2 构造方法
• public StringBuilder()
解释: 创建一个空白可变字符串对象, 它不含有任何内容.
• public StringBuilder(String str)
解释: 根据字符串的内容, 来创建可变字符串对象.
4.3 示例一: StringBuilder入门
需求
- 通过上述的两种方式, 创建StringBuilder对象.
- 在控制台直接打印上述创建好的两个对象, 并观察结果.
参考代码
public class Demo01 {
public static void main(String[] args) {
//1. 测试空参
StringBuilder sb = new StringBuilder();
System.out.println("sb: " + sb); //打印结果不是地址值, 说明StringBuilder已经重写了Object#toString()方法.
//2. 测试带参, 即: 把String对象 -> StringBuilder对象.
String s1 = "abc";
StringBuilder sb2 = new StringBuilder(s1);
System.out.println("sb2: " + sb2);
}
}
运行结果为:
sb:
sb2: abc
4.4 添加和反转方法
• public StringBuilder append(任意类型)
解释: 添加数据, 并返回对象本身.
• public StringBuilder reverse()
解释: 返回相反的字符序列.
需求
- 通过空参构造创建StringBuilder类的对象sb.
- 通过append()方法, 往sb对象中添加"hello",然后用sb2对象接收.
- 打印对象sb和sb2的结果, 并观察.
- 通过reverse()方法, 来反转上述的内容.
参考代码
public class Demo02 {
public static void main(String[] args) {
//1.通过空参构造创建StringBuilder类的对象sb.
StringBuilder sb = new StringBuilder();
//2.通过append()方法, 往sb对象中添加"hello",然后用sb2对象接收.
StringBuilder sb2 = sb.append("hello");
//3.打印对象sb和sb2的结果, 并观察.
System.out.println("sb: " + sb); //sb: hello
System.out.println("sb2: " + sb2); //sb2: hello
System.out.println(sb == sb2); //比较的是地址值, true
//实际开发中, append()方法的调用写法.
//如果是单个添加
sb.append("world");
//如果是添加多个, 用链式思想实现.
//复杂写法
/* sb.append("传智播客");
sb.append("黑马程序员");
sb.append("夯哥");*/
//链式编程解释: 如果一个方法的返回值还是对象, 我们可以在后边接着 .方法(), 这种写法就叫链式编程.
sb.append("传智播客").append("黑马程序员").append("夯哥");
System.out.println("sb: " + sb); //sb: helloworld
System.out.println("---------------------------");
//4.通过reverse()方法, 来反转上述的内容.
StringBuilder sb3 = sb2.reverse();
System.out.println("sb: " + sb);
System.out.println("sb2: " + sb2);
System.out.println("sb3: " + sb3);
System.out.println(sb2 == sb3);
}
}
运行结果为:
sb: hello
sb2: hello
true
sb: helloworld传智播客黑马程序员夯哥
---------------------------
sb: 哥夯员序程马黑客播智传dlrowolleh
sb2: 哥夯员序程马黑客播智传dlrowolleh
sb3: 哥夯员序程马黑客播智传dlrowolleh
true
4.5 StringBuilder和String之间的相互转换
• StringBuilder转化成String
解释: 可以通过StringBuilder#toString()方法直接实现.
• String转成StringBuilder
解释: 通过StringBuilder类的构造方法实现, `public StringBuilder(String s)
需求
- 定义空参不可变StringBuilder对象, 往里边添加完"hello"字符串后, 再将其转成String类型的对象.
- 将String字符串转成StringBuilder对象, 然后打印.
代码演示
public class Demo03 {
public static void main(String[] args) {
//1.定义空参不可变StringBuilder对象, 往里边添加完"hello"字符串后, 再将其转成String类型的对象.
StringBuilder sb = new StringBuilder();
sb.append("hello");
String s1 = sb.toString(); // StringBuilder对象 -> String对象
System.out.println("s1: " + s1);
System.out.println("--------------------");
//2.将String字符串转成StringBuilder对象, 然后打印.
String s2 = "传智播客";
StringBuilder sb2 = new StringBuilder(s2); //String对象 -> StringBuilder对象
System.out.println("sb2: " + sb2);
}
}
运行结果为:
s1: hello
--------------------
sb2: 传智播客
5. 冒泡排序
5.1 需求
- 已知数组int[] arr = {25, 69, 80, 57, 13}, 请编写代码对齐进行升序排序.
- 即: 排序后结果为: arr = {13, 25, 57, 69, 80};
5.2 原理
相邻元素两两比较, 大的往后走, 第一轮比较完毕后, 最大值就出现在了最大索引处.
5.3 图解
5.4 参考代码
public class Demo01 {
public static void main(String[] args) {
//1. 定义数组, 记录要排序的元素.
int[] arr = {25, 69, 80, 57, 13};
//2. 通过外循环, 控制比较的轮数.
//这里的-1是为了啥? 为了提高效率.
for (int i = 0; i < arr.length - 1; i++) {//0, 1, 2, 3
//3. 通过内循环, 控制每轮比较的次数.
/*
这里的-1是为了啥? 为了防止出现索引越界异常.
这里的-i是为了啥? 为了提高效率.
*/
for (int j = 0; j < arr.length - 1 - i; j++) { //4, 3, 2, 1
//4. 如果前一个元素比后一个元素大, 就交还它们的位置.
//即: arr[j] 和 arr[j + 1] 比较
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
//5. for循环执行结束后, 已经排好序了, 我们直接打印数组即可.
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
运行结果为:
13
25
57
69
80
6. Arrays类
6.1 概述
它是针对数组进行操作的工具类。提供了把数组转成字符串,对数组排序等功能。
工具类解释:
- 构造方法私有化.
- 成员方法都是静态的.
6.2 成员方法
• public static String toString(int[] arr)
解释: 把int类型的数组转成其对应的字符串形式.
• public static void sort(int[] arr)
解释: 对给定的int数组, 按照元素升序的顺序进行排序.
6.3 示例
需求
- 已知数组int[] arr = {25, 69, 80, 57, 13}.
- 通过Arrays#sort()方法, 对其升序排列.
- 打印排序后的结果.
参考代码
public class Demo02 {
public static void main(String[] args) {
//1. 定义数组
int[] arr = {25, 69, 80, 57, 13};
//2. 打印排序前的结果
System.out.println("排序前: " + Arrays.toString(arr));
//3. 对数组进行升序排列.
Arrays.sort(arr);
//4. 打印排序后的结果.
System.out.println("排序前: " + Arrays.toString(arr));
}
}
运行结果为:
排序前: [25, 69, 80, 57, 13]
排序后: [13, 25, 57, 69, 80]
6.4 Arrays类的构造方法问题
我们知道, 如果一个类中没有构造方法, 那么系统将提供一个空参构造方法. 而我们在帮助文档中没有看到Arrays类的构造方法. 这是为什么呢? 难道Arrays类真的没有构造方法吗?
答案是:
- Arrays类中有一个私有的空参构造方法, 这样做的目的是: 不让用户通过构造方法来创建Arrays类的对象.
- 因为Arrays类的成员都是静态的, 可以通过类名点的形式直接调用.
7. 包装类
假如让我们判断一个数据是否在int范围内, 首先我们的得知道int的范围, 在前边我们讲解数据类型的时候说过, 这个范围是: -2147483648 ~ 2147483647. 但是这个数据程序员不一定能记得住. 于是我们就想着, 如果有个变量或者常量能记录这个值该多好呢?
其实这个需求, 我们就可以通过Integer类的MAX_VALUE和MIN_VALUE两个常量来实现.
• public static final int MIN_VALUE
解释: 获取int类型所能表示的最小值
• public static final int MAX_VALUE
解释: 获取int类型所能表示的最大值
为了对基本类型进行更多更方便的操作, Java就针对每一种基本类型提供了一个对应的引用类型, 这就是包装类.
它们的对应关系如下:
基本类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
char | Character |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
7.2 最常见用法
包装类最常见的用法就是用于该类型对应的基本类型和字符串之间进行相互转换.
例如:
- Byte用于byte和String之间的相互转换.
- Integer用于int和String之间的相互转换.
- Double用于double和String之间的相互转换.
7.3 Integer类
7.3.1 概述
Integer 类是基本类型int所对应的包装类, 该类提供了多个方法,能在 int 类型和 String 类型之间互相转换,还提供了处理 int 类型时非常有用的其他一些常量和方法.
7.3.2 构造方法
• public Integer(int value)
解释: 把int类型的数据封装成其对应的Integer对象.
• public Integer(String s)
解释: 把字符串类型的整数封装成其对应的Integer对象.
注意: 这里传入的必须是纯数字类型的字符串.
7.3.3 示例
需求
- 通过上述的两个构造方法, 分别创建Integer类型的对象.
- 在main方法中, 打印创建好的Integer对象.
参考代码
public class Demo01 {
public static void main(String[] args) {
//1.通过上述的两个构造方法, 分别创建Integer类型的对象.
//1.1 演示: public Integer(int value);
Integer i1 = new Integer(10);
//1.2 演示: public Integer(String value);
Integer i2 = new Integer("123");
//Integer i2 = new Integer("123a"); 这样写会报错.
//2.在main方法中, 打印创建好的Integer对象.
System.out.println("i1: " + i1);
System.out.println("i2: " + i2);
System.out.println("----------------------------");
//3. 演示Integer类中的两个常量
System.out.println(Integer.MAX_VALUE); //int类型的最大值
System.out.println(Integer.MIN_VALUE); //int类型的最小值
}
}
运行结果为:
i1: 10
i2: 123
----------------------------
2147483647
-2147483648
7.3.4 int类型和String类型的相互转换
int类型 -> String类型
• 方式一: 直接在后边拼接""即可.
String s1 = 10 + "";
• 方式二: 通过String#valueOf()方法.
//public static String valueOf(int i)
String s1 = String.valueOf(10);
String类型 -> int类型
• 方式一: 通过String -> Integer -> int思路来实现.
//1. 先把String类型的对象转成Integer类型的对象.
String s1 = "10";
Integer i1 = new Integer(s1);
//2. 把Integer类型的对象转成int类型.
int num = i1.intValue();
• 方式二: 通过Integer#parseInt()方法来实现.
String s1 = 100;
int num = Integer.parseInt(s1);
7.3.5 示例
需求
- 已知字符串String s = “91 27 45 38 50”;
- 请通过代码实现最终输出结果是: “27, 38, 45, 50, 91”
提示
通过String类的split(String regex)方法, 可以按照指定字符切割字符串.
参考代码
import java.util.Arrays;
//案例: 演示字符串数字排序.
public class Demo01 {
public static void main(String[] args) {
//1. 定义变量, 记录要操作的字符串.
String s = "91 27 45 38 50";
//2. 把字符串转成其对应的字符串数组.
String[] strArray = s.split(" ");
//3. 定义和字符串数组长度一模一样的int[]
int[] arr = new int[strArray.length];
//4. 遍历字符串数组, 获取到每一个字符串.
for (int i = 0; i < arr.length; i++) {
//strArray[i]就是: 每一个字符串类型的数字, "91", "27"
//5. 把对应的字符串类型的整数转成其对应的 int类型的整数, 并填充到int[]中.
arr[i] = Integer.parseInt(strArray[i]);
}
//6. 对int[]进行排序.
Arrays.sort(arr);
//方式二: String#substring()方法, 分解版.
String s1 = Arrays.toString(arr); // "[27, 38, 45, 50, 91]"
//前边是起始索引, 后边是结束索引
String result = s1.substring(1, s1.length() - 1); //包左不包右
System.out.println(result);
System.out.println("-------------------");
//方式3: 合并版
String s2 = Arrays.toString(arr).substring(1, s1.length() - 1);
System.out.println("s2: " + s2);
}
}
运行结果为:
27, 38, 45, 50, 91
-------------------
s2: 27, 38, 45, 50, 91
7.3.6 自动拆装箱
• 把基本类型的数据封装成其对应的包装类型, 则称之为自动装箱.
//示例代码
Integer ii = 100; //自动装箱.
• 把包装类型的对象拆解成其对应的基本类型, 则称之为自动拆箱.
Integer ii = 100;
i1 += 200; //这排水口//自动装箱.
注意: 自动拆装箱都是JDK5的新特性.
需求
编写代码演示JDK1.5的新特性 , 自动拆装箱.
参考代码
public class Demo04 {
public static void main(String[] args) {
//需求: 编写代码演示JDK1.5的新特性 , 自动拆装箱.
//需求1: 演示自动装箱.
//1. 不采用自动装箱
int a = 10;
Integer i1 = new Integer(a);
//2. 自动装箱.
Integer i2 = a;
System.out.println("------------------------");
//需求2: 演示自动拆箱
//3. 不采用自动拆箱.
int b = i1.intValue();
//4. 采用自动拆箱.
int c = i1;
}
}
8. Date类
8.1 概述
Date类表示特定的瞬间,精确到毫秒. 它是java.util包下的类, 用之前需要先导包.
8.2 构造方法
• public Date();
解释: 根据当前系统时间, 获取其对应的Date对象.
• public Date(long date);
解释: 根据给定的整数, 获取其对应的Date对象.
8.3 案例: Date入门
需求
- 通过上述的两种方式创建Date对象.
- 在main方法中, 打印上述创建好的Date对象, 并观察结果.
参考代码
import java.util.Date;
//案例: 演示Date入门, 即Date的构造方法.
public class Demo01 {
public static void main(String[] args) {
//1. 演示 public Date(); 采用当前系统默认时间, 生成Date对象.
Date d1 = new Date();
System.out.println(d1);
System.out.println("---------------");
//2. 演示 public Date(long time); 采用指定的毫秒值, 生成对应的Date对象.
//Java中采用的时间原点是: 1970年1月1日 00:00:00
Date d2 = new Date(0L);
System.out.println(d2);
}
}
运行结果为:
Wed Apr 06 01:47:19 CST 2022
---------------
Thu Jan 01 08:00:00 CST 1970
8.4 成员方法
• public long getTime()
解释: 获取毫秒值.
• public void setTime(long time)
解释: 设置时间, 单位是毫秒值.
需求
编写代码, 测试上述的两个方法.
import java.util.Date;
public class Demo02 {
public static void main(String[] args) {
//1. 采用当前系统默认时间, 创建Date对L象.
Date d1 = new Date();
System.out.println(d1); //Mon Jun 01 12:07:33 CST 2020
//2. 获取上述时间对应的毫秒值.
System.out.println(d1.getTime()); //1590984453616
System.out.println("---------------------");
//2. 采用指定的毫秒值, 生成Date对象.
//Date d2 = new Date(1590984453616L);
Date d2 = new Date();
// 超int范围,后面加上L
d2.setTime(1634741997517L);
System.out.println(d2);
}
}
运行结果为:
Wed Apr 06 01:50:13 CST 2022
1649181013606
---------------------
Wed Oct 20 22:59:57 CST 2021
9. SimpleDateFormat类
9.1 概述
SimpleDateFormat 是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化和解析。
SimpleDateFormat类, 叫日期格式化类, 专门用来格式化和解析日期的.
• 格式化(日期 -> 文本), 即: Date -> String
• 解析(文本 -> 日期), 即: String -> Date
9.2 构造方法
• public SimpleDateFormat()
解释: 根据空参构造, 创建SimpleDateFormat类的对象.
• public SimpleDateFormat(String pattern)
解释: 根据给定的模板, 创建其对应的SimpleDateFormat类的对象.
9.3 成员方法
• public final String format(Date date)
解释: 用来格式化日期的.
• public Date parse(String source)
解释: 用来解析字符串形式的日期的.
9.4 示例一: 格式化日期
需求
把当前时间对象, 按照2020年3月4日 00:00:00格式进行打印.
参考代码
工具类:
public class DateUtils {
//1. 私有化构造方法.
private DateUtils() {
}
/**
* 2. 定义date2String(), 用来实现日期的格式化操作.
* @param d 要进行格式化操作的日期对象.
* @param pattern 模板.
* @return 当前日期对象格式化后的字符串形式.
*/
public static String date2String(Date d, String pattern) {
//2.1 创建SimpleDateFormat对象.
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
//2. 调用 SimpleDateFormat#format()方法, 用来实现日期的格式化操作.
return sdf.format(d);
}
/**
* 3. 定义string2Date(), 用来实现日期的解析操作.
* @param str 要进行解析操作的字符串.
* @param pattern 模板
* @return 指定的字符串解析后, 获取的Date对象.
* @throws ParseException 如果解析失败, 则抛出异常.
*/
public static Date string2Date(String str, String pattern) throws ParseException {
//3.1 创建SimpleDateFormat对象.
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
//3.2 调用SimpleDateFormat#parse()方法, 用来实现日期的解析操作.
return sdf.parse(str);
}
}
测试类:
import java.text.SimpleDateFormat;
import java.util.Date;
//案例: 演示SimpleDateFormat的格式化操作.
/*
SimpleDateFormat解释:
概述:
它是日期格式化类, 主要用来在Date和String之间做相互转换的.
构造方法:
public SimpleDateFormat(); 采用默认模板.
public SimpleDateFormat(String pattern); 采用指定模板.
成员方法:
public final String format(Date date); 日期格式化操作, 即: Date -> String
public Date parse(String source); 日期解析操作, 即: String -> Date
*/
public class Demo01 {
public static void main(String[] args) {
//需求: 把当前时间对象, 按照2020年3月4日 00:00:00格式进行打印.
//1. 获取当前时间.
Date d1 = new Date();
System.out.println(d1); //Mon Jun 01 14:31:50 CST 2020
System.out.println("--------------------");
//2. 通过SimpleDateFormat实现日期的格式化操作.
//2.1 创建SimpleDateFormat对象, 指定模板(可以自定义).
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//2.2 按照指定的模板进行格式化操作.
String result = sdf.format(d1);
//2.3 打印结果.
System.out.println(result);
}
}
运行结果为:
Wed Apr 06 01:57:26 CST 2022
--------------------
2022年04月06日 01:57:26
注意: 格式化日期的时候, 模板我们是可以自定义的.
10. Calendar类
10.1 概述
Calendar类叫: 日历类, 是方便我们操作日期的. 它里边的功能大多数是用来替代java.util.Date类的功能的.
10.2 构造方法
Calendar类可以理解为是工具类, 因为它是一个抽象类, 所以外界无法通过new的方式创建本类对象.
问题: 如何创建Calendar类的对象呢?
答案: 通过Calendar#getInstance()方法实现.
10.3 示例一: Calendar入门
需求 通过上述的方式, 创建Calendar对象.
参考代码
public class Demo01 {
public static void main(String[] args) {
//需求: 创建Calendar对象.
//Calendar c = new Calendar的子类对象();
//多态. 底层帮助我们创建了Calendar类的子类对象.
Calendar c = Calendar.getInstance();
}
}
10.4 成员变量
• public static final int YEAR
解释: 表示年份.
• public static final int MONT
解释: 表示月份.
• public static final int DATE
解释: 表示年中的某一天.
• public static final int DAYOFMONTH
解释: 表示月中的某一天.
• public static final int DAYOFWEEK
解释: 表示星期中的某一天.
10.5 成员方法
• public static Calendar getInstance();
解释: 创建Calendar类型的子类对象.
• public int get(int field)
解释: 根据日历字段, 获取其对应的值.
• public void set(int year, int month, int day)
解释: 设置时间为指定的年, 月, 日.
• public void add(int field, int count)
解释: 修改指定的时间为指定的偏移量, 例如: 往前推2天, 推3个月, 往后推2年.
10.6 示例二: 获取指定的年月日
需求
- 通过上述的方法, 获取当前的年, 月, 日信息.
- 打印结果.
参考代码
public class Demo02 {
public static void main(String[] args) {
//需求: 获取当前的年月日, 然后打印.
//1. 获取Calendar类的对象.
Calendar c = Calendar.getInstance();
//2. 获取当前年份.
int year = c.get(Calendar.YEAR); //推荐掌握, 成员变量名的形式.
//int year2 = c.get(1); //1是 Calendar.YEAR这个成员变量对应的值, 不建议记忆这种方式.
System.out.println(year);
//System.out.println(year2);
//3. 获取当前月份.
int month = c.get(Calendar.MONTH);
System.out.println(month); //5, 因为Java中月份的范围是: 0~11
//4. 获取当前的日期(年中的某天)
int day1 = c.get(Calendar.DAY_OF_YEAR);
System.out.println(day1); //153
//5. 获取当前的日期(月中的某天).
int day2 = c.get(Calendar.DAY_OF_MONTH); //1
System.out.println(day2);
//6. 获取当前的日期(星期中的某天)
int day3 = c.get(Calendar.DAY_OF_WEEK); //2, 老外时间, 周日是星期中的第一天.
System.out.println(day3);
}
}
运行结果为:
2022
3
96
6
4