目录
11.LocalData、LocalTime、LocalDataTime
1.认识API
2.Object
import java.util.Objects;
public class Student {
private String name;
private int age;
private double score;
public Student() {
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
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;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
/**
*比较者:t1 ==> this
* 被比较者:t2 ==> o
*
*/
@Override
public boolean equals(Object o) {
//1.判断两个对象是否是同一个对象在比较,如果是,直接返回true
if (this == o) return true;
//2.判断o如果是null,直接返回false,或者两个对象的类型不一样,直接返回false
if (o == null || this.getClass() != o.getClass()) return false;
//3.两个对象肯定都是学生类型,且是不同对象,开始比较内容了!
Student student = (Student) o;
return this.age == student.age && Double.compare(this.score, student.score) == 0 &&
Objects.equals(this.name, student.name);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", score=" + score +
'}';
}
}
package com.itheima.d11_object;
public class Test {
public static void main(String[] args) {
//目标:掌握Object的常用方法
Student s1 = new Student("小昭",21,100);
//1.toString默认返回对象的所谓的地址形式其实是没有意义的,开发中输出对象对象更想看内容,因此toString是为了让子类重写
//System.out.println(s1.toString());//直接输出对象时,toString可以不写
System.out.println(s1);
System.out.println("----------------------");
//2.equals方法默认是比较两个对象的地址是否一样
//比较两个对象的地址是否一样可以直接用"=="比较,完全没必要用equals比较
//因此Object提供的equals的意义是为了让子类重写,以便自己制定比较规则(按照内容比较!)
Student t1 = new Student("殷素素",35,98);
Student t2 = new Student("殷素素",35,98);
System.out.println(t1.equals(t2));//true
System.out.println(t1 == t2);//false
}
}
3.Objects类
java中带s的一般都是工具类
import java.util.Objects;
public class Test {
public static void main(String[] args) {
//目标:掌握Objects的常用方法
Student t1 = null;
Student t2 = new Student("蜘蛛精",300,85.5);
//System.out.println(t1.equals(t2));//如果主调对象是null,直接爆出空指针异常
// public static boolean equals(Object a, Object b) {
// return (a == b) || (a != null && a.equals(b));
// }
//更安全,更可靠,,会进行非空校验,推荐使用
//今后比较两个对象时,建议用Objects的equals来判断
System.out.println(Objects.equals(t1,t2));
System.out.println(Objects.isNull(t1));//true
System.out.println(t1 == null);//true
System.out.println(Objects.nonNull(t1));//false
System.out.println(t1 != null);//false
}
}
4.包装类
万物皆对象,java中的对象是在堆内存中储存的,而八种基本数据类型是在栈内存中储存的。
在 Java 中,Integer
自动装箱机制是指将基本数据类型int
自动转换为其对应的包装类Integer
对象的过程。这个特性使得 Java 可以在基本类型和对象之间无缝切换,提高了代码的简洁性和可读性。
自动装箱的工作原理:当你将一个int
值赋给Integer
对象时,Java 编译器会自动调用Integer.valueOf(int)
方法。
Integer a = 100; // 自动装箱,等价于 Integer a = Integer.valueOf(100);
缓存机制的细节:
Java 为了优化性能,对Integer
类做了特殊处理:
-
缓存范围:在 - 128 到 127 之间的
Integer
对象会被缓存。 -
内存优化:当使用
valueOf()
创建这个范围内的对象时,会复用缓存中的实例,而不是每次都创建新对象。 -
超出范围:对于范围外的值(如 128 或 - 129),每次都会创建新的
Integer
对象。
以下代码展示了缓存机制的效果:
public class IntegerCacheDemo {
public static void main(String[] args) {
// 范围内的比较
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // 输出true,因为指向同一个缓存对象
// 超出范围的比较
Integer c = 128;
Integer d = 128;
System.out.println(c == d); // 输出false,因为是不同的对象
// 使用new关键字总是创建新对象
Integer e = new Integer(100);
Integer f = new Integer(100);
System.out.println(e == f); // 输出false,因为是不同的对象
}
}
package com.itheima.d13_integer;
public class Test {
public static void main(String[] args) {
//目标:认识包装类,搞清楚包装类的作用
int a = 12;
//1.把基本类型通过包装类包装成对象。
//Integer it1 = new Integer(a);//已过时
Integer it1 = Integer.valueOf(a);//手动包装
System.out.println(it1);
//2.自动装箱机制,基本类型的数据可以直接变成对象赋值给包装类。
Integer it2 = 12;
Integer it3 = 12;
System.out.println(it2 == it3);//true
//-128~127会在内存中缓存为同一个对象,超过127后才会new新的对象
//3.自动拆箱机制,包装类的对象可以直接赋值给基本数据类型
int it4 = it3;
System.out.println(it4);
System.out.println("-------java为包装类提供了新功能----------");
//1.功能一:包装类可以把基本类型的数据转换为字符串
int a1 = 23;
String rs = Integer.toString(a1);
System.out.println(rs + 1);//231
Integer i = a1;
String rs2 = i.toString();//"23"
System.out.println(rs2 + 1);//231
int a2 = 23;
String rs3 = a2 + "";//这样更简单
System.out.println(rs3 + 1);
//2.功能二:把字符串数据转换成对应的基本数据类型(很有用!!!)
String ageStr = "23";
//int age = Integer.parseInt(ageStr);
int age = Integer.valueOf(ageStr);
System.out.println(age + 1);//24
String scoreStr = "99.5";
//double score = Double.parseDouble(scoreStr);
double score = Double.valueOf(scoreStr);
System.out.println(score + 0.5);//100.0
//3.由于泛型和集合都不支持基本数据类型,因为万物皆对象,因此包装类在集合和泛型中大量使用而且是必须使用的
}
}
由于泛型和集合都不支持基本数据类型,因为万物皆对象,因此包装类在集合和泛型中大量使用而且是必须使用的(简单操作用基本类型,集合泛型用包装类)
5.StringBuilder
public class StringBuilderDemo2 {
public static void main(String[] args) {
//目标:进行StringBuilder拼接字符串的性能测试
//1.使用String拼接,看效率如何
// String s = "";
// for (int i = 0; i < 1000000; i++) {
// s += "abc";//堆内存中不断产生垃圾对象,性能差
// }
// System.out.println(s);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000000; i++) {
sb.append("abc");
}
System.out.println(sb);
}
}
- 对于字符串相关的操作,如频繁的拼接、修改等,建议用StirngBuilder,效率更高!
- 注意:如果字符串较少,或者不需要操作,以及字符串变量,还是建议用String。
- StringBuilder 是用来高效拼接字符串的类。它内部维护着一个可变的字符数组,在进行字符串拼接时,不会像 String 那样频繁创建新对象,从而显著提升了性能。
在单线程环境下,应优先使用 StringBuilder;在多线程环境下,则需使用 StringBuffer 以保证线程安全。
5.1 StringBuilder案例
public class StringBuilderTest3 {
public static void main(String[] args) {
//目标:使用StringBuilder完成对字符串的拼接操作
int[] arr = {11, 44, 33, 66};
System.out.println(getArrayData(arr));
}
public static String getArrayData(int[] arr){
if(arr == null){
return null;
}
//1.创建StringBuilder对象
StringBuilder sb = new StringBuilder();
sb.append("[");
//2.遍历数组中的内容
for (int i = 0; i < arr.length; i++) {
int data = arr[i];
sb.append(data).append(i == arr.length - 1 ? "" : ", ");
}
sb.append("]");
return sb.toString();
}
}
6.StringJoiner
import java.util.StringJoiner
public class StringJoinerTest1 {
public static void main(String[] args) {
//目标:使用StringJoiner完成对字符串的拼接操作
int[] arr = {11, 44, 33, 66};
System.out.println(getArrayData(arr));
}
public static String getArrayData(int[] arr){
if(arr == null){
return null;
}
//1.创建StringJoiner对象
//参数一:间隔符 参数二:开始符号 参数三:结束符号
StringJoiner sb = new StringJoiner(", " ,"[","]");
//2.遍历数组中的内容
for (int i = 0; i < arr.length; i++) {
sb.add(Integer.toString(arr[i]));
}
return sb.toString();
}
}
7.Math
8.Runtime 
9.System
/**
* 目标:了解下System类的常见方法。
*/
public class SystemTest {
public static void main(String[] args) {
// 1、public static void exit(int status):
// 终止当前运行的Java虚拟机。
// 该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。
System.out.println("开始。。");
// System.exit(0); // 0代表是正常终止JVM虚拟机 (禁止使用)
// 2、public static long currentTimeMillis():返回的是从1970-1-1 00:00:00 走到此刻的总毫秒值(1s = 1000ms)
long time = System.currentTimeMillis(); // 获取系统的时间毫秒值。
System.out.println(time);
// 可以做性能统计
for (int i = 0; i < 1000000; i++) {
System.out.println(i);
}
long time2 = System.currentTimeMillis(); // 获取系统的时间毫秒值。
System.out.println((time2 - time) / 1000.0 + "s");
}
}
10.BigDecimal(!!!)
第一个构造器public BigDecimal(double val)只能解决运算时数据过大的问题(即使超过了double的范围),无法解决运算精度问题,所以不推荐。
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalDemo1 {
public static void main(String[] args) {
//目标:学会处理浮点型运算失真的问题
double a = 0.1;//让数字用二进制表示出来
double b = 0.2;
double c = a + b;
//尽量的用二进制拼接出接近结果的数字
System.out.println(c);//0.30000000000000004
//1.把两个数据包装成BigDecimal对象
// public BigDecimal(String val):这个接收字符串的构造器才可以处理失真问题。
BigDecimal a1 = new BigDecimal(Double.toString(a));
BigDecimal b1 = new BigDecimal(Double.toString(b));
//b.阿里巴巴公司更推荐我们用valueOf方法包装浮点型数据成为iBigDecimal对象
//跟上面的做法本质是一样的,更简洁,不需要转字符串
BigDecimal a11 = BigDecimal.valueOf(a);
BigDecimal b11 = BigDecimal.valueOf(b);
//2.调用方法进行精度运算
// BigDecimal c11 = a11.add(b11);//加
// BigDecimal c11 = a11.subtract(b11);//减
// BigDecimal c11 = a11.multiply(b11);//乘
BigDecimal c11 = a11.divide(b11);//除
//调用方法恢复成浮点型
//再恢复为浮点型基本类型接数据在栈里面不用跨区域到堆里面找数据,性能好
//对象会从栈到堆,而基本类型数据在栈里面
//3.BigDecimal是处理精度问题的手段,结果必须还是基本类型
double result = c11.doubleValue();
System.out.println(result);
System.out.println("------------------------");
BigDecimal i = BigDecimal.valueOf(0.1);
BigDecimal j = BigDecimal.valueOf(0.3);
/**
* 参数一:除数
* 参数二:保留位数
* 参数三:舍入模式
*/
//public BigDecimal divide(BigDecimal divisor, int roundingMode)
BigDecimal k = i.divide(j,2, RoundingMode.HALF_UP);//没有精确的结果
System.out.println(k);
}
}
11.LocalData、LocalTime、LocalDataTime
package com.itheima.d5_jdk8_time;
import java.time.LocalDate;
import java.util.Calendar;
public class Test1_LocalDate {
public static void main(String[] args) {
// 0、获取本地日期对象(不可变对象)
LocalDate ld = LocalDate.now();
System.out.println(ld);
// 1、获取日期对象中的信息
int year = ld.getYear(); // 年
int month = ld.getMonthValue(); // 月
int day = ld.getDayOfMonth(); // 日
int dayOfYear = ld.getDayOfYear(); // 一年中的第几天
int dayOfWeek = ld.getDayOfWeek().getValue(); // 星期几
System.out.println(year);
System.out.println(month);
System.out.println(day);
System.out.println(dayOfYear);
System.out.println(dayOfWeek);
// 2、直接修改某个信息: withYear、withMonth、withDayOfMonth、withDayOfYear
LocalDate ld2 = ld.withYear(2099);
LocalDate ld3 = ld.withMonth(12);
System.out.println(ld2);
System.out.println(ld3);
System.out.println(ld);
// 3、把某个信息加多少: plusYears、plusMonths、plusDays、plusWeeks
LocalDate ld4 = ld.plusYears(2);
LocalDate ld5 = ld.plusMonths(2);
System.out.println(ld4);
// 4、把某个信息减多少:minusYears、minusMonths、minusDays、minusWeeks
LocalDate ld6 = ld.minusYears(2);
LocalDate ld7 = ld.minusMonths(2);
// 5、获取指定日期的LocalDate对象: public static LocalDate of(int year, int month, int dayOfMonth)
LocalDate ld8 = LocalDate.of(2099, 12, 12);
LocalDate ld9 = LocalDate.of(2099, 12, 12);
// 6、判断2个日期对象,是否相等,在前还是在后: equals isBefore isAfter
System.out.println(ld8.equals(ld9));// true
System.out.println(ld8.isAfter(ld)); // true
System.out.println(ld8.isBefore(ld)); // false
}
}
package com.itheima.d5_jdk8_time;
import java.time.LocalTime;
public class Test2_LocalTime {
public static void main(String[] args) {
// 0、获取本地时间对象
LocalTime lt = LocalTime.now(); // 时 分 秒 纳秒 不可变的
System.out.println(lt);
// 1、获取时间中的信息
int hour = lt.getHour(); //时
int minute = lt.getMinute(); //分
int second = lt.getSecond(); //秒
int nano = lt.getNano(); //纳秒
// 2、修改时间:withHour、withMinute、withSecond、withNano
LocalTime lt3 = lt.withHour(21);
LocalTime lt4 = lt.withMinute(10);
LocalTime lt5 = lt.withSecond(10);
LocalTime lt6 = lt.withNano(10);
System.out.println(lt);
// 3、加多少:plusHours、plusMinutes、plusSeconds、plusNanos
LocalTime lt7 = lt.plusHours(10);
LocalTime lt8 = lt.plusMinutes(10);
LocalTime lt9 = lt.plusSeconds(10);
LocalTime lt10 = lt.plusNanos(10);
// 4、减多少:minusHours、minusMinutes、minusSeconds、minusNanos
LocalTime lt11 = lt.minusHours(10);
LocalTime lt12 = lt.minusMinutes(10);
LocalTime lt13 = lt.minusSeconds(10);
LocalTime lt14 = lt.minusNanos(10);
// 5、获取指定时间的LocalTime对象:
// public static LocalTime of(int hour, int minute, int second)
LocalTime lt15 = LocalTime.of(12, 12, 12);
LocalTime lt16 = LocalTime.of(12, 12, 12);
// 6、判断2个时间对象,是否相等,在前还是在后: equals isBefore isAfter
System.out.println(lt15.equals(lt16)); // true
System.out.println(lt15.isAfter(lt)); // false
System.out.println(lt15.isBefore(lt)); // true
}
}
package com.itheima.d5_jdk8_time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Test3_LocalDateTime {
public static void main(String[] args) {
// 最重要的一个类。
// 0、获取本地日期和时间对象。
LocalDateTime ldt = LocalDateTime.now(); // 年 月 日 时 分 秒 纳秒 不可变对象
System.out.println(ldt);
// 1、可以获取日期和时间的全部信息
int year = ldt.getYear(); // 年
int month = ldt.getMonthValue(); // 月
int day = ldt.getDayOfMonth(); // 日
int dayOfYear = ldt.getDayOfYear(); // 一年中的第几天
int dayOfWeek = ldt.getDayOfWeek().getValue(); // 获取是周几
int hour = ldt.getHour(); //时
int minute = ldt.getMinute(); //分
int second = ldt.getSecond(); //秒
int nano = ldt.getNano(); //纳秒
// 2、修改时间信息:
// withYear withMonth withDayOfMonth withDayOfYear withHour
// withMinute withSecond withNano
LocalDateTime ldt2 = ldt.withYear(2029);
LocalDateTime ldt3 = ldt.withMinute(59);
// 3、加多少:
// plusYears plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanos
LocalDateTime ldt4 = ldt.plusYears(2);
LocalDateTime ldt5 = ldt.plusMinutes(3);
// 4、减多少:
// minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanos
LocalDateTime ldt6 = ldt.minusYears(2);
LocalDateTime ldt7 = ldt.minusMinutes(3);
// 5、获取指定日期和时间的LocalDateTime对象:
// public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour,
// int minute, int second, int nanoOfSecond)
//方法是重载的,可以少写参数默认为0
LocalDateTime ldt8 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);
LocalDateTime ldt9 = LocalDateTime.of(2029, 12, 12, 12, 12, 12, 1222);
// 6、 判断2个日期、时间对象,是否相等,在前还是在后: equals、isBefore、isAfter
System.out.println(ldt9.equals(ldt8));
System.out.println(ldt9.isAfter(ldt));
System.out.println(ldt9.isBefore(ldt));
// 7、可以把LocalDateTime转换成LocalDate和LocalTime
// public LocalDate toLocalDate()
// public LocalTime toLocalTime()
// public static LocalDateTime of(LocalDate date, LocalTime time)
// 合久必分
LocalDate ld = ldt.toLocalDate();
LocalTime lt = ldt.toLocalTime();
// 分久必合
LocalDateTime ldt10 = LocalDateTime.of(ld, lt);
}
}
12.Zonedld、ZonedDateTime
package com.itheima.d5_jdk8_time;
import java.time.Clock;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Set;
public class Test4_ZoneId_ZonedDateTime {
public static void main(String[] args) {
// 目标:了解时区和带时区的时间。
// 1、ZoneId(用于获取时区的)的常见方法:
// public static ZoneId systemDefault(): 获取系统默认的时区
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId.getId());
System.out.println(zoneId);
// public static Set<String> getAvailableZoneIds(): 获取Java支持的全部时区Id
Set<String> zoneIds = ZoneId.getAvailableZoneIds();
System.out.println(zoneIds);
// public static ZoneId of(String zoneId) : 把某个时区id封装成ZoneId对象。
// America/New_York
ZoneId an = ZoneId.of("America/New_York");
// 2、ZonedDateTime:带时区的时间。
// public static ZonedDateTime now(ZoneId zone): 获取某个时区的ZonedDateTime对象。
// public static ZonedDateTime now():获取系统默认时区的ZonedDateTime对象
// ZonedDateTime 的功能和 LocalDateTime一样了
ZonedDateTime zdt = ZonedDateTime.now(an);
System.out.println(zdt);
// 世界标准时间了: 很多服务器要获取世界时间!
ZonedDateTime utcNow = ZonedDateTime.now(Clock.systemUTC());
System.out.println(utcNow);
}
}
13.Instant
package com.itheima.d5_jdk8_time;
import java.time.Instant;
import java.time.LocalDateTime;
/**
* 目标:掌握Instant的使用。
*/
public class Test5_Instant {
public static void main(String[] args) {
// 1、创建Instant的对象,获取此刻时间信息。
Instant now = Instant.now();
System.out.println(now);
// 2、获取总秒数
System.out.println(now.getEpochSecond());
// 3、不够1秒的纳秒数
System.out.println(now.getNano());
// Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点
}
}
14.DateTimeFoematter
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/**
* 目标:掌握JDK 8新增的DateTimeFormatter格式化器的用法。
*/
public class Test6_DateTimeFormatter {
public static void main(String[] args) {
// 1、创建一个日期时间格式化器对象出来。
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss EEE a");
// 2、对时间进行格式化
LocalDateTime ldt = LocalDateTime.now();
String result = dtf.format(ldt);
System.out.println(result);
// 3、格式化时间,其实还有一种方案。
String result2 = ldt.format(dtf);
System.out.println(result2);
// 4、解析时间:解析时间一般使用LocalDateTime提供的解析方法来解析。
String dateStr = "2023-11-11 11:11:11";
// 第一步:必须写一个日期时间格式化器与这个时间的格式一模一样。
DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt2 = LocalDateTime.parse(dateStr, dtf2);
System.out.println(ldt2);
}
}
15.Period、Duration
package com.itheima.d5_jdk8_time;
import java.time.LocalDate;
import java.time.Period;
/**
* 目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。
*/
public class Test7_Period {
public static void main(String[] args) {
LocalDate start = LocalDate.of(2024, 3, 19);
LocalDate end = LocalDate.of(2024, 10, 13);
// 1、创建Period对象,封装两个日期对象。
Period period = Period.between(start, end);
// 2、通过period对象获取两个日期对象相差的信息。
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
}
}
import java.time.Duration;
import java.time.LocalDateTime;
public class Test8_Duration {
public static void main(String[] args) {
LocalDateTime start = LocalDateTime.of(2025, 11, 11, 11, 10, 10);
LocalDateTime end = LocalDateTime.of(2025, 11, 11, 11, 11, 11);
// 1、得到Duration对象
Duration duration = Duration.between(start, end);
// 2、获取两个时间对象间隔的信息
System.out.println(duration.toDays());// 间隔多少天
System.out.println(duration.toHours());// 间隔多少小时
System.out.println(duration.toMinutes());// 间隔多少分
System.out.println(duration.toSeconds());// 间隔多少秒
System.out.println(duration.toMillis());// 间隔多少毫秒
System.out.println(duration.toNanos());// 间隔多少纳秒
}
}
16.案例—高考时间
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class Test10 {
public static void main(String[] args) {
// 目标:高考倒计时。
// 1、高考时间是
String startTime = "2026-06-07 09:30:00";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt1 = LocalDateTime.parse(startTime, dtf);
// 2、知道此刻离高考时间差多少天,多少时,多少分,多少秒。
LocalDateTime ldt2 = LocalDateTime.now();
// 3、计算两个时间差
Duration duration = Duration.between(ldt2, ldt1);
System.out.println(duration.toDays() + "天" + duration.toHoursPart() + "时"
+ duration.toMinutesPart() + "分" + duration.toSecondsPart() + "秒");
}
}
注意在拿到时,分,秒时要在对应的方法后面加Part,否则拿到的是总的时间。