Java中常用的工具类
学习目标
- 了解日期类
- 了解格式化转换类
- 了解加解密有关操作
1.日期类
● java.util包是Java内置的一个工具包,其中包含一系列常用的工具类;
● 如处理日期和日历的类以及一些集合类;
● java.util包不会默认导入,如果要使用到该包中的类,则必须在程序的开始部分显式地声明如下语句:import java.util.*;
1.1 Date
● Date类对象用来表示时间和日期;该类提供一系列操纵日期和时间各组成部分的方法;
● Date类最多的用途是获取系统当前的日期和时间。
● jdk1.8之前使用率非常高的日期类
1.1.1 常用构造
Date类的构造方法有6种重载方式,很多已经过时,以下是比较常用的2种。
方法定义 | 描述 |
---|---|
public Date() | 使用系统当前时间创建日期对象 |
public Date(long date) | 使用距离1970年1月1日零点零分的毫秒数对应的日期创建日期对象 |
1.1.2 常用方法
除了getTime方法之外,其他方法基本不用;因为Date类型是属于比较老的日期类型,目前新项目中使用较少;
方法定义 | 描述 |
---|---|
public long getTime() | 返回该日期时间对象距离1970-1-1 0.0.0 0毫秒之间的毫秒值 |
public static void main(String[] args) {
//java.util.Date 表示一个特定的日期的时间
//jdk1.8+ Date建议过时
//new Date();
//new Date(long millsecond)
Date date = new Date();//当前系统此刻的时间
System.out.println(date);
//功能方法
long time = date.getTime();//获得指定时间的毫秒数
System.out.println(time);
Date date1 = new Date(time);
System.out.println(date);
//一般获得当前时间戳 时间毫秒数
// Date.getTime()
long timeMillis = System.currentTimeMillis();
System.out.println(timeMillis);
}
1.2 Calendar
● Calendar类也是用来操作日期和时间的类,但它可以以整数形式检索类似于年、月、日之类的信息;
● Calendar类是抽象类,无法实例化,要得到该类对象只能通过调用getInstance方法来获得;
● Calendar对象提供为特定语言或日历样式实现日期格式化所需的所有时间字段
● JDK1.8之后推荐使用Calendar替换Date。
1.2.1 常用方法
方法定义 | 描述 |
---|---|
public static Calendar getInstance() | 根据默认时区返回对应的calendar对象; |
public final Date getTime() | 返回具有相同时间的Date对象;可以理解为把一个Calender对象转化为对应时间的Date对象; |
public int get(int field) | 用于获取 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段对应的时间值。 |
public void set(int field, int value) | 用于设置 YEAR、MONTH、DAY_OF_MONTH、HOUR 等 日历字段对应的时间值。 |
private static void calendarDemo() {
//获得Calendar对象
Calendar calendar = Calendar.getInstance();//系统当前此刻日历时间
System.out.println(calendar);
//具体日期属性数据 get
getInfo(calendar);
//+10天
//calendar.set(Calendar.DAY_OF_MONTH,calendar.get(Calendar.DATE)+10);
calendar.add(Calendar.DATE, 30);
System.out.println("---------------------------");
getInfo(calendar);
//Calendar 与 Date相互转换
Date date = calendar.getTime();
calendar.setTime(new Date());
}
private static void getInfo(Calendar calendar) {
System.out.println(calendar.get(Calendar.YEAR));
System.out.println(calendar.get(Calendar.MONTH) + 1);
System.out.println(calendar.get(Calendar.DAY_OF_MONTH));
System.out.println(calendar.get(Calendar.DATE));
System.out.println(calendar.get(Calendar.HOUR));
System.out.println(calendar.get(Calendar.MINUTE));
System.out.println(calendar.get(Calendar.SECOND));
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));
}
private static void monthCalendarDemo() {
//展示特定一个月份的完整的日历信息
System.out.println("日\t一\t二\t三\t四\t五\t六");
//1.获得Calendar对象
Calendar calendar = Calendar.getInstance();
//2.修改特定月份
calendar.set(Calendar.MONTH, Calendar.JULY);
calendar.set(Calendar.DATE, 1);
int num = calendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < num; i++) {
System.out.print("\t");
}
//3.获得当前月份最大天数
int totalDay = calendar.getActualMaximum(Calendar.DATE);
for (int day = 1; day <= totalDay; day++) {
System.out.print(day + "\t");
//当前day是这一周的最后一天 换行
calendar.set(Calendar.DATE, day);
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) {
System.out.println();
}
}
}
1.2.2 问题
● Java1.0中包含了一个Date类,但是它的大多数方法已经在Java 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
○ 可变性:像日期和时间这样的类对象应该是不可变的。Calendar类中可以使用三种方法更改日历字段:set()、add() 和 roll()。
○ 偏移性:Date中的年份是从1900开始的,而月份都是从0开始的。
○ 格式化:格式化只对Date有用,Calendar则不行。
○ 此外,它们也不是线程安全的,不能处理闰秒等。
1.3 Instant
● JDK8的应用,推荐使用 Instant 代替 Date。
● 所谓的 Instant 类代表的是某个时间(有点像 java.util.Date),它是精确到纳秒的(而不是像旧版本的Date精确到毫秒);
● Instant 时间线上的瞬间点,采用UTC的时间刻度。
● Instant 代表的是一个时间,并不包括时区的概念,所以必须传入的是符合 UTC格式的字符串;
● 此类是不可变的且是线程安全的。在java.time.* 包下 1.8 版本才有
1.3.1 常用方法
方法定义 | 描述 |
---|---|
public static Instant now() | 返回系统时间对应的Instant实例 |
Temporal plus(long amountToAdd, TemporalUnit unit) | 返回一个增加具体时间的Instant实例; |
Temporal minus(long amountToSubtract, TemporalUnit unit) | 返回一个减去具体时间的Instant实例; |
public class InstantDemo {
private static void test1() {
// Instant instant =
// Instant.now(Clock.offset(Clock.systemUTC(),Duration.ofHours(8)));
Instant instant = Instant.now();
// System.out.println(instant);
instant = instant.plusSeconds(8 * 60 * 60);// 加8个小时 转换成秒数
System.out.println(instant);
// instant = instant.plus(Duration.ofHours(8));
// instant = instant.plus(8, ChronoUnit.HOURS);
// int milliOfSecond = instant.get(ChronoField.MILLI_OF_SECOND);
System.out.println(Instant.now());
long duration = instant.until(Instant.now(), ChronoUnit.HOURS);// 获得2个时间对象的间隔 转换成特定的时间单位
System.out.println(duration);
}
}
1.4 Local日期类
● 本地日期时间:LocalDate、LocalTime、LocalDateTime;
● 都是线程安全且不可变;
1.4.1 常用方法
方法 | 描述 |
---|---|
now() / now(ZoneId zone) | 静态方法,根据当前时间创建对象/指定时区的对象 |
of() | 静态方法,根据指定日期/时间创建对象 |
getDayOfMonth()/getDayOfYear() | 获得月份天数(1-31) /获得年份天数(1-366) |
getDayOfWeek() | 获得星期几(返回一个 DayOfWeek 枚举值) |
getMonth() | 获得月份, 返回一个 Month 枚举值 |
getMonthValue() / getYear() | 获得月份(1-12) /获得年份 |
getHours()/getMinute()/getSecond() | 获得当前对象对应的小时、分钟、秒 |
withDayOfMonth()/withDayOfYear()/withMonth()/withYear() | 将月份天数、年份天数、月份、年份修改为指定的值并返回新的对象 |
with(TemporalAdjuster t) | 将当前日期时间设置为校对器指定的日期时间 |
plusDays(), plusWeeks(), plusMonths(), plusYears(),plusHours() | 向当前对象添加几天、几周、几个月、几年、几小时 |
minusMonths() / minusWeeks()/minusDays()/minusYears()/minusHours() | 从当前对象减去几月、几周、几天、几年、几小时 |
plus(TemporalAmount t)/minus(TemporalAmount t) | 添加或减少一个 Duration 或 Period |
isBefore()/isAfter() | 比较两个 LocalDate |
isLeapYear() | 判断是否是闰年(在LocalDate类中声明) |
format(DateTimeFormatter t) | 格式化本地日期、时间,返回一个字符串 |
parse(Charsequence text) | 将指定格式的字符串解析为日期、时间 |
- LocalDate
private static void test1() {
LocalDate localDate = LocalDate.now();
System.out.println(localDate);
System.out.println(localDate.getYear());
System.out.println(localDate.getDayOfWeek());
localDate = localDate.minusMonths(1);
System.out.println(localDate);
LocalDate date1 = LocalDate.of(2022, 3, 20);
System.out.println(date1);
}
- LocalDateTime
private static void testLocalDateTime() {
LocalDateTime localDateTime = LocalDateTime.now();
System.out.println(localDateTime);//2022-12-5T14:54:00.375
localDateTime = localDateTime.minusMonths(10);
System.out.println(localDateTime);
System.out.println(new Date());// 2022年12月5日 12:00:00 星期一
}
- LocalTime
private static void testLocalTime() {
LocalTime localTime = LocalTime.now();
System.out.println(localTime);// 14:48:12.525
LocalTime localTime2 = LocalTime.of(23, 59, 59);
System.out.println(localTime2);
System.out.println(localTime.getHour());
System.out.println(localTime.getMinute());
System.out.println(localTime.plusHours(2));
System.out.println(localTime.minusMinutes(50));
}
1.5 间隔相关的日期类
● Period:用于计算两个“日期”间隔
● Duration:用于计算两个“时间”间隔
public static void main(String[] args) {
LocalDate t1 = LocalDate.now();
LocalDate t2 = LocalDate.of(2022, 12, 5);
Period between = Period.between(t1, t2);
System.out.println("相差的年数:" + between.getYears());
System.out.println("相差的月数:" + between.getMonths());
System.out.println("相差的天数:" + between.getDays());
}
public static void main(String[] args) {
LocalDateTime t1 = LocalDateTime.now();
LocalDateTime t2 = LocalDateTime.of(2022, 12, 9, 0, 0, 0, 0);
Duration between = Duration.between(t1, t2);
System.out.println(between);
System.out.println("相差的总天数:"+between.toDays());
System.out.println("相差的总小时数:"+between.toHours());
System.out.println("相差的总分钟数:"+between.toMinutes());
System.out.println("相差的总秒数:"+between.getSeconds());
System.out.println("相差的总毫秒数:"+between.toMillis());
System.out.println("相差的总纳秒数:"+between.toNanos());
System.out.println("一秒内的纳秒数:"+between.getNano());
}
2.格式化类
public abstract class Format implements Serializable, Cloneable {}
public abstract class DateFormat extends Format {}
public abstract class NumberFormat extends Format {}
public class SimpleDateFormat extends DateFormat {}
public class DecimalFormat extends NumberFormat {}
2.1 日期格式化
1.DateFormat
● 在显示日期的时候,可以使用很多格式,这时我们就可以借助java.text包中的DateFormat类及其子类进行调整;
● SimpleDateFormat 用于Date 类型的格式化。
● DateFormat属于抽象类,我们使用子类SimpleDateFormat ,只针对于Date类型数据进行格式化操作。
○ public final String format(Date date)将一个 Date 格式化为日期/时间字符串。
○ public Date parse(String source)throws ParseException从给定字符串的开始解析文本,以生成一个日期对象。
public class DateUtil {
private DateUtil() {
}
private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
//SimpleDateFormat 线程不安全的类 不能作为全局变量使用
/**
* String转Date
* 从前到后
* @param dateStr
* @return
*/
public static Date strToDate(@NonNull String dateStr) {
DateFormat dateFormat = new SimpleDateFormat(PATTERN);
Date date = null;
try {
date = dateFormat.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
/**
* date转String
* 从后到前
* @param date
* @return
*/
public static String dateToStr(@NonNull Date date) {
DateFormat dateFormat = new SimpleDateFormat(PATTERN);
return dateFormat.format(date);
}
}
2 DateTimeFormatter
如果是jdk1.8相关的几个日期类做转换的话,就必须使用DateTimeFormatter;
- LocalDate 与 String相互转换
public static void main(String[] args) {
// LocalDate.parse(text, formatter)
LocalDate date1 = LocalDate.of(2022, 3, 20);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd");
String str = formatter.format(date1);
System.out.println(str);// 2022年03月20
LocalDate date1 = LocalDate.parse(str, formatter);// 2022-3-20
System.out.println(date1);
}
- LocalDateTime与String相互转换
public static void main(String[] args) {
LocalDateTime localDateTime = LocalDateTime.of(2024, 12, 2, 10, 10, 10);
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd HH时mm分ss秒");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str = formatter.format(localDateTime);
System.out.println(str);
LocalDateTime parse = LocalDateTime.parse(str, formatter);
System.out.println(parse);
}
- Instant与String相互转换
public static void main(String[] args) {
Instant instant = Instant.now();
// 将Instant 转换成string DateTimeFormatter
//必须带有时区的设置,因为Instant是和时区相关的日期类
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneId.systemDefault());
String str = formatter.format(instant);
System.out.println("日期字符串: " + str);
// String 转换成 Instant
Instant parse = Instant.parse("2022-12-8T06:33:13.034Z");// 默认是这种格式的时间 否则无法转换
System.out.println(parse);
}
2.2 NumberFormat
● 要格式化数字,可以使用NumberFormat类来实现
● NumberFormat也是抽象类,必须使用子类DecimalFormat
● #.## 保留两位小数
● #.##% 自动百分比计数并保留两位小数
● ,### 每三位以逗号分隔
public static void main(String[] args) {
// 创建格式化数字对象
// NumberFormat numberFormat = new DecimalFormat("#.##%");
// String result = numberFormat.format(0.456777);
// System.out.println(result);
NumberFormat numberFormat = new DecimalFormat("###,###.###");
String result = numberFormat.format(4567778827.626548);
System.out.println(result);
}
3.随机数类
● Random类专门用来生成随机数;
● ThreadLocalRandom是Random的子类。
● 在并发程序中使用ThreadLocalRandom而不是共享的Random对象通常会遇到更少的开销和争用。 当多个任务在线程池中并行使用随机数时,使用ThreadLocalRandom是特别合适的。
3.1 常用构造
方法定义 | 描述 |
---|---|
public Random() | 直接创建一个Random类的对象 |
public Random(long seed) | 使用seed作为随机种子创建一个Random类的对象 |
3.2 常用方法
方法定义 | 描述 |
---|---|
public int nextInt() | 返回一个随机数整型值 |
public long nextLong() | 返回一个随机数长整型值 |
public float nextFloat() | 返回一个随机浮点型值,0.0到1.0之间的单精度值 |
public double nextDouble() | 返回一个随机浮点型值,0.0到1.0之间的双精度值 |
public class RandomDemo {
public static void main(String[] args) {
// 创建一个Random类对象
Random rand = new Random();
// 随机生成20个随机整数,并将其显示出来
for (int i = 0; i < 20; i++) {
int num = rand.nextInt();
System.out.println("第" + (i + 1) + "个随机数是:" + num);
}
}
}
private static void demo2() {
ThreadLocalRandom random = ThreadLocalRandom.current();
//获得1000-10000
for (int i = 0; i < 5; i++) {
System.out.println(random.nextInt(1000, 10000));
}
}
4.编码解码类
4.1 Base64
● Base64 加解密。jdk1.8可正常使用。
● Base64.Encoder Base64.Decoder
public static void main(String[] args) {
// 注册 对密码进行编码
String pass = "1234";
Base64.Encoder encoder = Base64.getEncoder();// 获得编码器
String encodePass = encoder.encodeToString(pass.getBytes());
System.out.println(encodePass);// MTIzNA==
// 登陆
Base64.Decoder decoder = Base64.getDecoder();// 获得解码器
byte[] by = decoder.decode(encodePass);
String str = new String(by);
System.out.println(str);
if (pass.equals(str)) {
System.out.println("用户登陆成功");
}
}
4.2 MessageDigest
● MessageDigest类为应用程序提供消息摘要算法的功能,如SHA-1或SHA-256或MD5。
● 消息摘要是采用任意大小的数据并输出固定长度散列值的安全单向散列函数。
public static void main(String[] args) {
String pass = "123456";
try {
// 1.获得messageDigest对象
MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
// 2.传输需要加密数据
messageDigest.update(pass.getBytes());
// 3.加密
byte[] encodeBy = messageDigest.digest();
System.out.println(Arrays.toString(encodeBy));
// 将字节数组转换成BigInteger实例
BigInteger bigInteger = new BigInteger(1, encodeBy);
String pass1 = bigInteger.toString(16);
//密文
System.out.println(pass1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}