1.Object
作用
一个类要么默认继承了Object类,要么间接继承了Object类,Object类是Java中的祖宗类
Object类的方法是一切子类都可以直接使用的
Object类的常用方法
方法名 | 说明 |
public String toString() | 默认是返回当前对象在堆内存中的地址信息:类的全限名@内存地址 |
public Boolean equas(Object o) | 默认是比较当前对象与另一个对象的地址是否相同,相同返回true |
toString存在意义
父类toString()方法存在的意义就是为了被子类重写,以便返回对象的内容信息,而不是地址信息
public class Student {
private String name;
private char sex;
private int age;
public Student() {
}
public Student(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", sex=" + sex +
", age=" + age +
'}';
}
}
equals存在的意义
父类equals方法存在的意义就是为了被子类重写,以便子类自己来定制比较规则
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return sex == student.sex && age == student.age && Objects.equals(name, student.name);
}
2.Objects
Object类与Object还是继承关系,Objects类是从JDK1.7之后才有的
官方在进行字符串比较时,没有对象自己的equals方法,而是选择了Objects的equals方法来比较两个对象
Objects的equals方法比较的结果是一样的,但是更安全
Objects的常见方法
方法名 | 说明 |
public static boolean equals(Object a, Object b) | 比较两个对象的,底层会先进行非空判断,从而可以避免空指针异常,再进行equals比较 |
public static boolean isNull(Object obj) | 判断变量是否为null,为null返回true,反之 |
public class Test {
public static void main(String[] args) {
String s1 = null;
String s2 = new String("张三");
// System.out.println(s1.equals(s2));
System.out.println( Objects.equals(s1, s2)); // 更安全,更准确
System.out.println(Objects.equals(s, s1));
}
}
3.StringBuilder
StringBuilder是一个可变的字符串类,可以把它堪称是一个对象容器
作用:提高字符串的操作效率,如拼接,修改等
StringBuilder构造器
名称 | 说明 |
public StringBuilder | 创建一个空白的可变的字符串对象,不包含任何内容 |
public StringBuilder(String str) | 创建一个指定字符串内容的可变字符串对象 |
StringBuilder常用方法
方法 | 说明 |
public StringBuilder append(任意类型) | 添加数据并返回StringBuilder对象本身 |
public StringBuilder reverse() | 将对象的内容反转 |
public int length() | 返回对象内容长度 |
public String toString() | 通过toString()就可以实现把StringBuilder转换为String |
public class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("a");
sb.append("2");
sb.append(222);
System.out.println(sb);
StringBuilder sb1 = new StringBuilder();
sb1.append("a").append(2).append(3);
System.out.println(sb1);
System.out.println(sb1.length());
}
}
案例:打印整型数组的内容
public class Test2 {
public static void main(String[] args) {
int[] arr1 = {2,3,5,5,6};
System.out.println(arrToString(arr1));
}
public static String arrToString(int[] arr) {
if(arr != null) {
StringBuilder s = new StringBuilder("[");
for (int i = 0; i < arr.length; i++) {
s.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");
}
s.append("]");
return s.toString();
}else {
return null;
}
}
}
4.Math类
包含执行基本数字运算的方法,Math类没有提供公开的构造器
Math类的常用方法
方法 | 说明 |
public static int abs(int a) | 获取参数绝对值 |
public static idouble ceil(doublle a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static int round(float a) | 四舍五入 |
public static int max(int a) | 获取两个int值中的较大值 |
publlic static double pow(double a, double b) | 返回a的b次幂的值 |
public static double random() | 返回值为doublle的随机值,范围[0.0,1.0] |
5.System类
System的功能是通用的,都是直接用类名调用即可,所以System不能被实例化
System类的常用方法
方法 | 说明 |
public static void exit(int status) | 终止当前运行的Java虚拟机,非零表示异常终止 |
public static long currentTimeMills() | 返回当前系统的时间毫秒值形式 |
public static void arraycope(数据源数组,起始索引,目的地数组,起始拷贝,拷贝个数) | 数组拷贝 |
public class Test {
public static void main(String[] args) {
System.out.println("程序中断");
long time = System.currentTimeMillis();
System.out.println(time);
int[] arr1 = {10,20,30,40,50, 60, 70};
int[] arr2 = new int[6];
System.arraycopy(arr1, 2, arr2, 2, 3);
System.out.println(Arrays.toString(arr2));
System.exit(0); // JVM终止
System.out.println("00");
}
}
6.BigDecimal
用于解决浮点型运算精度失真问题
使用步骤
创建对象BigDecimal
public static BigDecimal valueOf(double val); // 包装浮点数成为BigDecimal对象
BigDecima常用API
方法名 | 说明 |
public BigDecimall add(BigDecimal b) | 加法 |
public BigDecimall subtract(BigDecimal b) | 减法 |
public BigDecimall multiply(BigDecimal b) | 乘法 |
public BigDecimall divide(BigDecimal b) | 除法 |
public BigDecimall divide(另一个BigDecimall对象,精确几位,舍入模式) | 除法 |
public class Test {
public static void main(String[] args) {
double a = 0.1;
double b = 0.2;
double c = a + b;
System.out.println(c);
BigDecimal a1 = BigDecimal.valueOf(a);
BigDecimal a2 = BigDecimal.valueOf(b);
BigDecimal c1 = a1.add(a2);
System.out.println(c1);
BigDecimal c2 = a1.multiply(a2);
System.out.println(c2);
double e = 10;
double f = 3;
BigDecimal a11 = BigDecimal.valueOf(e);
BigDecimal a22 = BigDecimal.valueOf(f);
BigDecimal c3 = a11.divide(a22, 2, RoundingMode.HALF_UP);
System.out.println(c3);
}
}
7.Date类
Date类的对象在Java中代表的是当前所在系统的此刻日期时间
Date的构造器
public Date() 创建一个Date对象,代表的是系统当前此刻日期时间
Date的常用方法
public long getTime() 获取时间对象的毫秒值
public static void main(String[] args) {
// 1. 创建一个Date类的兑现,代表系统此刻日期时间对象
Date d = new Date();
long time = d.getTime();
System.out.println(d);
System.out.println(time);
}
时间毫秒值->日期对象
public Date(long time) 把时间毫秒值转换成Date日期对象
public void setTime(long time) 设置日期对象的时间为当前时间毫秒值对应的时间
SimpleDateFormat类作用
可以把对象或时间毫秒值格式化成常用的时间格式
也可以把字符串时间形式解析成日期对象
SimpleDateFormat的构造器
public SimpleDateFormat() 构造一个SimpleDateFormat,使用默认格式
public SimpleDateFormat(String pattern) 构造一个SimpleDateFormat,使用指定的格式
SimpleDateFormat的格式化方法
public final String format(Date date) 将日期格式化成日期/时间字符串
public final String format(Object time) 将时间毫秒值格式化成日期/时间字符串
public static void main(String[] args) {
Date d = new Date();
System.out.println(d);
// 格式化日期
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");
String rs = sdf.format(d);
System.out.println(rs);
}
SimpleDateFormat解析字符串时间成为日期对象
public Date parse(String source) 从给定字符串的开始解析文本以生成日期
public static void main(String[] args) throws ParseException {
// 使用SimpleDateFormat解析字符串时间为日期对象
// 有一个时间2022年07月05日 13:30:30往后2天20小时20分09秒后的时间是多少
String dateStr = "2022年07月05日 13:30:30";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = sdf.parse(dateStr);
long time = d.getTime() + (2L*24*60*60 + 20*60*60+20*60+9)*1000;
System.out.println(sdf.format(time));
}
8.案例:秒杀活动
需求:秒杀开始时间为 2022年 6月18日 00:00:00 - 2022年6月18日 00:10:00
小明下单并付款的时间为 2022年6月18日 00:03:58
小张下单并付款的时间为 2022年6月18日 00:10:38
判断他们是否秒杀成功
public static void main(String[] args) throws ParseException {
// 1.开始和结束时间
String startTime = "2022-06-18 00:00:00";
String endTime = "2022-06-18 00:10:00";
// 2.小明小张时间
String xiaoming = "2022-06-18 00:03:58";
String xiaozhang = "2022-06-18 00:10:38";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d1 = sdf.parse(startTime);
Date d2 = sdf.parse(endTime);
Date d3 = sdf.parse(xiaoming);
Date d4 = sdf.parse(xiaozhang);
if(d3.after(d1) && d3.before(d2)) {
System.out.println("小明秒杀成功");
} else {
System.out.println("小明秒杀失败");
}
if(d4.after(d1) && d4.before(d2)) {
System.out.println("小张秒杀成功");
} else {
System.out.println("小张秒杀失败");
}
}
9.Calendar
Calendar代表了系统此刻日期对应的日历对象
Calendar是一个抽象类,不能直接创建对象
Calendar常用方法
public int get(int field) 取日期中的某个字段信息
public void set(int field, int value) 修改日历的某个字段信息
public void add(int field, int amount) 为某个字段增加/减少指定的值
public final Date getTime() 拿到此刻日期对象
public long getTimeInMillis() 拿到此刻时间毫秒值
注意:calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化
10.JDK8新增日期类
从Java8开始,Java.time包提供了新的日期和时间API,主要涉及的类类型有
LocalDate: 不包含jurisdiction时间的日期
LocallTime: 不含日期的时间
LocalDateTime: 包含了日期及时间
Instant: 代表的是时间戳
DateTimeFormatter 用于做时间的格式化和解析的
Duration: 用于计算两个“时间”间隔
Period:用于计算两个“日期”间隔
新增的API严格区分了时刻、本地日期、本地时间,并且,对日期和时间进行运算更加方便
其次,新API的类类型几乎全部是不变类型(和String的使用类似),可以放心使用不必担心被修改
LocalDate、LocalTime、LocalDateTime
分别表示日期、时间、日期时间对象,它们的类的实例是不可变的对象
它们构建对象和API都是通用的
LocalDateTime综合了LocalDate和LocalTime里面的方法
这些方法返回的是一个新的实例的引用
plusDays, plusWeeks, plusMonths, plusYears 向当前LocalDate对象添加几天、几周、几个月,几年
minusDays, minusWeeks, minusMonths, minusYears 从当前LocalDate对象减去几天、几周、几个月、几年
withDayOfMonth, withDayOfYear, withMonth, withYear 将月份天数、年份天数、月份、年份修改为指定的值并返回新的LocalDate对象
isBefore,isAfter 比较两个LocalDate
Instant时间戳
时间戳是包含日期和时间的,与java.util.Date很类似,事实上Instant就是类似JDK8之前的Date
Instant和Date这两个类可以进行转换
public static void main(String[] args) {
// 得到一个Instant时间戳对象
Instant instant = Instant.now();
System.out.println(instant);
// 系统此刻时间戳
Instant instant1 = Instant.now();
System.out.println(instant1.atZone(ZoneId.systemDefault()));
// 如何返回Date对象
Date date = Date.from(instant);
System.out.println(date);
}
DateTimeFormatter
在JDK8中,引入了一个全新的日期与格式器DateTimeFormatter
正反都能调用format方法
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss EEE a");
System.out.println(dtf);
DateTimeFormatter dtf1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt1 = LocalDateTime.parse("2022-11-11 11:11:11", dtf1);
System.out.println(ldt1);
}
Period
在Java8中。可以使用java.time.Period
主要是Period类方法getYear(), getMonths() 和getDays() 来计算,只能精确到年月日
用于LocalDate之间的比较
public static void main(String[] args) {
LocalDate today = LocalDate.now();
System.out.println(today);
LocalDate b = LocalDate.of(2010,10,11);
System.out.println(b);
Period period = Period.between(b, today);
System.out.println(period.getYears());
}
Duration
public static void main(String[] args) {
LocalDateTime today = LocalDateTime.now();
System.out.println(today);
LocalDateTime b = LocalDateTime.of(2010,10,11, 20: 20: 01);
System.out.println(b);
Duration d = Duration.between(b, today);
System.out.println(d.getYears());
}
11.包装类
包装类就是8种基本数据类型对应的引用类型
基本数据类型 | 引用数据类型 |
byte | Byte |
short | Short |
int | Integer |
long | Long |
char | Character |
float | Float |
double | Double |
boolean | Boolean |
为什么提供包装类
Java为了实现一切皆对象,为8种基本类型提供来了对应的引用类型
集合和泛型其实也只能支持包装类型,不支持基本数据类型
自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量
自动拆箱:包装类型的变量可以直接赋值给基本数据类类型的变量
包装类的特有功能
包装类的变量的默认值可以是null,容错率更高
可以把基本类型的数据转换成字符串类型
调用toString() 方法得到字符串结果
调用Integer.toString(基本类型的数据)
可以把字符串类型的数值转换成真是的数据类型
Integer.parseInt(“字符串类型的整数”)
Double.parseDouble(“字符串类型的小数”)
valueOf() 效果一样
public static void main(String[] args) {
int a = 10;
Integer a1 = 11;
Integer a2 = a; // 自动装箱
System.out.println(a);
System.out.println(a);
Integer i = 100;
int i2 = i; // 自动拆箱
System.out.println(i2);
// int age = null;
Integer age2 = null;
}
12.正则表达式
正则表达式可以用一些规定的字符来指定规则,并用来校验数据格式的合法性
字符串对象提供了匹配正则表达式规则的API
public boolean matched(String regex);
// 验证码 必须是数字和字符 且为4位
System.out.println("12cd".matches("[a-zA-Z0-9]{4}"));
System.out.println("12cd".matches("[\\w&&[^_]]{4}"));
案例:使用正则表达式完成如下需求
1.便且程序模拟用户输入手机号码,验证格式是否正确,并给出提示,直到格式输入正确为止
2.便且程序模拟用户输入邮箱号码,验证格式是否正确,并给出提示,直到格式输入正确为止
3.便且程序模拟用户输入电话号码,验证格式是否正确,并给出提示,直到格式输入正确为止
public static void checkTel() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请您输入需要验证的电话号码");
String tel = sc.next();
if (tel.matches("0\\d{2,6}-?\\d{5,20}")) {
System.out.println("电话号码格式正确");
break;
}else {
System.out.println("电话格式有误");
}
}
}
public static void checkEmail() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请您输入需要验证的邮箱号码");
String email = sc.next();
if (email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")) {
System.out.println("邮箱号码格式正确");
break;
}else {
System.out.println("邮箱格式有误");
}
}
}
public static void checkPhone() {
Scanner sc = new Scanner(System.in);
while (true) {
System.out.println("请您输入需要验证的手机号码");
String phone = sc.next();
if (phone.matches("1[3-9]\\d{9}")) {
System.out.println("手机号码格式正确");
break;
}else {
System.out.println("格式有误");
}
}
}
正则表达式在字符串方法中的使用
public String replaceAll(String regex, String newStr) 按照正则表达式匹配的内容进行替换
public String[] split(String regex) 按照正则表达式匹配的内容进行分割字符串,返回一个字符串数组
public static void main(String[] args) {
String name = "张三123456李四123456王五123456赵六";
String[] arr = name.split("\\w+");
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
正则表达式爬取信息
public static void main(String[] args) {
String rs = "张三电话010-231399,邮箱2345678@qq.com,手机13452337895";
String regex = "\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}|1[3-9]\\d{9}|0\\d{2,6}-?\\d{5,20}";
// 把这个爬取规则编译成匹配对象
Pattern pattern = Pattern.compile(regex);
// 得到一个内容匹配器对象
Matcher matcher = pattern.matcher(rs);
// 寻找
while (matcher.find()) {
String rs1 = matcher.group();
System.out.println(rs1);
}
}
13.Arrays类
数组操作工具类,专门用于处理数组元素
Array类的常用API
public static String toString(类型[] a) 对数组进行排序
public static void sort(类型[] a) 对数组进行默认升序排序
public static <T> void sort(类型[] a.Comparator<?super T?>c) 使用比较器对象自定义排序
public static int binarySearch(int[] a, int key) 二分搜索数组中的数据,存在返回索引,不存在返回-1
public static void main(String[] args) {
int[] arr = {20, 21, 15, 40, 34};
System.out.println(arr);
// 返回数组内容
String rs = Arrays.toString(arr);
System.out.println(rs);
// 排序(自动对数组元素进行升序排序)
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
// 二分搜索技术(前提数组必须排好序才支持,否则出bug)
// 返回不存在元素的规律 -(应该插入位置的索引+1)
int index = Arrays.binarySearch(arr, 40);
System.out.println(index);
}
自定义排序规则
设置Comparator接口对比的比较器对象,来定制比较规则
如果认为左边数据大于右边数据返回正整数
如果认为左边数据小于右边数据返回负整数
如果认为左边数据等于右边数据返回0
// 定义Student类
public static void main(String[] args) {
// Comparator比较器对象
Integer[] arr = {10, 22, 45,3,12,34};
// 降序排序(自定义比较器对象,只能支持引用类型的排序)
Arrays.sort(arr, new Comparator<>(){
@Override
public int compare(Integer o1, Integer o2) {
// 指定比较规则
return o1-o2;
}
});
System.out.println(Arrays.toString(arr));
Student[] students = new Student[3];
students[0] = new Student("张三", 23, 178.5);
students[1] = new Student("李四", 22, 167.5);
students[2] = new Student("王五", 25, 165.5);
System.out.println(Arrays.toString(students));
Arrays.sort(students, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// return o1.getAge() - o2.getAge();
return Double.compare(o1.getHeight(),o2.getHeight()); // 比较浮点型
}
});
System.out.println(Arrays.toString(students));
}
}
14.排序方法
选择排序
每轮选择当前位置,开始找出后面的较小值与该位置交换
public static void main(String[] args) {
int[] arr = {2,3,5,1,7,9};
for (int i = 0; i < arr.length-1; i++) {
for (int j=i; j< arr.length-1;j++) {
if(arr[i]>arr[j]) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
二分查找
在数据量特别大的时候,基本查找从前往后寻找的性能是很差的
二分查询性能好,二分查找的前提是必须是排序好的数据
二分查找正常的检索条件应该是开始位置min<= 结束位置max
public static int binarySearch(int[] arr, int data) {
int left = 0;
int right = arr.length -1;
// 开始循环,这般查询
while (left <= right) {
// 取中间索引
int middleIndex = (left + right) / 2;
// 判断当前中间位置元素和要找的元素的大小情况
if(data> arr[middleIndex]) {
left = middleIndex + 1;
}else if(data< arr[middleIndex]) {
right = middleIndex-1;
} else {
return middleIndex;
}
}
return -1;
}
步骤
定义变量记录左边和右边位置
使用while循环控制查询(条件是左边位置<=右边位置)
循环内部获取中间元素索引
判断当前要找的元素如果大于中间元素,左边位置=中间索引+1
判断当前要找的元素如果等于中间元素,右边位置=中间索引-1
判断当前要找的元素如果等于中间元素,返回当前中间元素索引
15.Lambda表达式
Lambda表达式是JDK 8开始后的一种新语法形式
作用:简化匿名内部类的代码写法
Lambda表达式的简化形式
(匿名内部类被重写方法的形参列表) -> {
被重写方法的方法体代码
}
注意:Lambda表达式只能简化函数时接口的匿名内部类的写法形式
首先必须是接口、其次接口中有且仅有一个抽象方法的形式
通常会在接口上加上一个@FunctionalInterface注解,标记该接口满足函数式接口
public class Test {
public static void main(String[] args) {
Run r1 = new Run() {
@Override
public void run() {
System.out.println("人在跑");
}
};
go(r1);
Run r2 = () -> {
System.out.println("狗在跑");
};
go(r2);
}
public static void go(Run r) {
System.out.println("开始");
r.run();
System.out.println("结束");
}
}
@FunctionalInterface // 一旦加上这个注释必须是函数时接口,里面只能有一个抽象方法
interface Run {
void run();
}
好处:Lambda是一个匿名函数,可以把Lambda表达式理解为是一段可以传递的代码,它可以写出更简洁、更灵活的代码,作为一种更紧凑的代码风格,使Java语言表达能力得到了提升
Lambda表达式的省略规则
参数类型可以不写
如果只有一个参数,参数类型可以省略,同时()也可以省略
如果Lambda表达式的方法体代码只有一行,可以省略大括号不写,同时要省略分号
如果Lambda表达式的方法体代码只有一行代码,可以生路大括号不写,此时,如果这行代码是return语句,必须省略return不屑,同时也必须省略分号不写