Java常用工具类
Java常用工具类
Object类
Object类是类层次结构的根。每个类都有 Object作为超类。所有对象,包括数组,实现这个类的方法。
getClass()方法
返回该 Object运行时类。返回的 类对象是由类的代表 static synchronized方法锁定对象。
hashCode()方法
public int hashCode()
返回一个对象的哈希代码值。这种方法对于hash表,如所提供的 HashMap利益支持
//基本数据类型没有hashCode()
public static void main(String[] args) {
//每new一个对象hashcode都不同
Student s1 = new Student();
Student s2 = new Student();
int a=10;
int ai = new Integer(10);
System.out.println(a==ai);//true
System.out.println("===================");
/**
* 基本类型使用==,是比较基本类型的本身是否相等
* 引用类型==,是比较变量存放的地址值
*/
System.out.println(s1==s2);//false
//引用类
System.out.println(s1.hashCode()==s2.hashCode());//false
Student s3=s2;
System.out.println(s3==s2);//true
System.out.println(s3.hashCode()==s2.hashCode());//true
System.out.println("=========================");
String t1="y1";
String y="y",s="1";
String ys=y+s;//y1
String yi = new String("y2");
System.out.println(t1.hashCode()==yi.hashCode());//false
//基本数据类型没有hashCode()
System.out.println(t1.hashCode()==ys.hashCode());//true
System.out.println(t1==yi);//false
System.out.println(t1.equals(yi));//true
String t2=t1+"er";
System.out.println(t1.hashCode()==t2.hashCode());//false
}
}
class Student{
}
equals()方法
public boolean equals(Object obj)
指示是否有其他对象“等于”这一个。
==:
基本数据类型比较:比较的是值
引用数据类型比较:比较的是内存地址(hashcode)
equals:
基本数据类型比较:无法使用
引用数据类型比较:源码为==,所以还是比较的是内存地址
对象equals源码
public boolean equals(Object obj) {
return (this == obj);
}
String类型equals源码,也是重写了equals方法,将String转换为基本数据类型char,然后来进行比较
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
类中重写equals方法
public class Test02 {
public static void main(String[] args) {
String name = "张三";
String name1 = "张三";
System.out.println(name.equals(name1));//true
System.out.println(name==name1);//true
A1 a1 = new A1("张三",10);
A1 a2 = new A1("张三",10);
//因为在a1类中重写了equals方法,判断(String,int)是相同即为true,若不重写则比较的是内存为false
System.out.println(a1.equals(a2));//true
System.out.println(a1==a2);//false
}
}
class A1{
String name;
int age;
public A1() {
}
public A1(String name, int age) {
this.name = name;
this.age = age;
}
//重写父类equals方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
A1 a1 = (A1) o;
return age == a1.age && Objects.equals(name, a1.name);
}
}
toString()方法
public String toString()
返回对象的字符串表示形式。总的来说,这 toString方法返回一个字符串,“以文本方式表示”这个对象。其结果应该是一个简洁,但翔实的代表性,是一个容易阅读的人。建议所有子类都重写此方法。
Object类的toString方法返回一个包含该类的对象是一个实例的名称字符串的符号 @` ',和符号进制表示的对象的哈希码。换句话说,此方法返回一个等于值的字符串:
getClass().getName() + '@' + Integer.toHexString(hashCode())
// Class类重写了Object toString()
System.out.println(A1.class.toString());//class com.xiaoming.objectClass.A1
System.out.println(a1.toString());//com.xiaoming.objectClass.A1@4554617c
Object类toString()源码
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
Class类重写toString()源码
public String toString() {
return (isInterface() ? "interface " : (isPrimitive() ? "" : "class "))
+ getName();
}
clone()方法
创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类。
protected native Object clone() throws CloneNotSupportedException;
clone()object类必须先实现Cloneable接口,然后在重写clone方法。如果不实现Cloneable接口则会报CloneNotSupportedException错误,
clone出来的对象和原来对象是两个完全不同内存地址的对象
public class Test03 {
public static void main(String[] args) throws CloneNotSupportedException {
A2 a2 = new A2();//a2:1163157884
A2 a4 = (A2) a2.clone();
System.out.println(a2==a4);//false
Object clone = a2.clone(); //clone:1956725890
//强制转换不会改变hashcode值
A2 a3= (A2) clone;//a3:1956725890
System.out.println(a2==clone);//false
System.out.println(a2==a3);//false
System.out.println(clone==a3);//true
}
}
class A2 implements Cloneable{
String name;
int age;
public A2(String name, int age) {
this.name = name;
this.age = age;
}
public A2() {
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
深克隆和浅克隆:
深克隆:克隆该对象的所有子父关系。除了对象本身被复制外,对象包含的引用也被复制,也就是其中的成员 对象也被复制
浅克隆:只克隆该对象。浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象
JAVA语言中,**序列化(Serialization)**就是将对象写到流的过程,写到流中的对象是原有的对象的一个拷贝,而原对象仍存在内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且也可以复制其引用的成员对象,因此通过序列化将对象写入一个流中,再从流中将其读出来,从而实现深克隆。
finaliaz()方法
当垃圾收集确定没有对对象的引用时,由对象上的垃圾收集器调用。子类重写 finalize方法配置系统资源或执行其他清理。
protected void finalize() throws Throwable { }
该方法是finalize最多只调用一次java虚拟机在任何给定的对象。
任何异常的原因finalize方法抛出这个对象最终被叫停,但被忽视。
final:修饰符,作用在属性上该属性为常量,不能被修改,作用在方法上该方法不能被继承
finaly:异常中用于出现异常最后会执行的代码,常见的是关闭I/O流关闭资源
notify()方法
唤醒一个在这个对象的监视器上等待的单个线程。如果任何线程都在等待这个对象,其中一个被选择被唤醒。选择是任意的,发生在执行的自由裁量权。一个线程等待一个对象的监控通过调用其中的 wait方法。
此方法只应被一个线程的所有者,该线程是这个对象的监视器的所有者。
异常:于IllegalMonitorStateException -如果当前线程不拥有此对象监视器。
public final native void notifyAll();
notifyAll()方法
唤醒正在等待此对象监视器上的所有线程。一个线程等待一个对象的监控通过调用其中的 wait方法。
public final void notifyAll();
wait()方法
使当前线程等待另一个线程调用此对象的方法或notify() notifyAll()方法。换句话说,这个方法的行为就好像它仅执行呼叫 wait(0)。
public final native void wait(long timeout) throws InterruptedException;
这种方法应该只被一个线程是拥有此对象监视器。看到一个描述的方式,一个线程可以成为监视器所有者的 notify方法。
wait(long timeout)
使当前线程等待另一个线程调用此对象的方法或 notify() notifyAll()方法,或一个指定的时间流逝。
public final native void wait(long timeout) throws InterruptedException;
wait(long timeout, int nanos)
使当前线程等待另一个线程调用此对象的方法或notify() notifyAll()方法,或者其他某个线程中断当前线程,或一定量的实际时间已经过去了。
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
String类
String类表示的字符串。java程序中的所有字符串,如 "abc",实现这个类的实例。
public final class String
extends Object
implements Serializable, Comparable<String>, CharSequence
由final修饰:String字符串是常量,它们的值不能被创建后改变。支持可变字符串字符串缓冲区。因为字符串对象是不可改变的,所以它们可以被共享。
继承了Object类可以重写equals()等方法
String类型内存分析
//在方法区中的常量池添加一个"zhansan"并在栈区生成一个name指向"zhangsan"
String name="zhansan";
//在常量池中查找无果后生成一个666的常量,并且将name(zhangsan)拼接成一个新的常量"zhangsan666",此时的栈区会生成一个name指向拼接的常量
name=name+"6666";
//在常量池中无果后生成一个"name:"的常量,并且将name(zhangsan666)拼接成一个新的常量"name:zhangsan666"
sout("name:"+name)

//在常量池中查找到有相同的String常量,所以在栈中name2指向的是常量池中已经创建好的"zhangsan"
String name2="zhangsan";

String a = "abc";
char[] data= {'a','b','c'};
String b = new String(data);
System.out.println(a==b);//false
//equals被string类重写,比较的是值
System.out.println(a.equals(b));//true
//string每次改变都会创建一个新的常量
System.out.println(a.hashCode());//96354
a += "d";
System.out.println(a.hashCode());//2987074
//因为字符串对象是不可改变的,所以它们可以被共享。
String c = "efg";
String d = "efg";
System.out.println(d==c);//true
System.out.println("d:"+d.hashCode()+"c:"+c.hashCode());//d:100326 c:100326
内存分析:

String类型的特点:
如果发现在方法区中没有对应的字符串,会自动开辟内存存储新的字符串
字符串一旦创建了,是不能够被修改的
字符串虽然不能够被修改,但是可以共享
如果字符串频繁的拼接字符串,都会在方法区开辟空间,这样是非常消耗内存空间的,所有如果字符串拼接比较频繁不建议使用String类型,这时我们可以改用StringBuffer或者StringBuilder
String中的构造方法

String() 初始化新创建的 String对象,它代表了一个空字符序列。
String(byte[] bytes) 通过使用平台的默认字符集解码指定的字节数组构造了一个新的 String。
String(char[] value) 分配一个新的 String,它代表了目前包含在字符数组参数字符序列。
String(char[] value, int offset, int count) 分配一个包含字符与字符数组数组参数的新 String。
用法:分配一个包含字符与字符数组数组参数的新 String。的说法是 offset的子阵列的第一个字符的索引和 count参数指定的数组的长度。的子阵列的内容复制的字符数组;随后的修改不影响新创建的字符串。
Parameters:
value阵列是字源
offset -初始偏移
count -长度
char[] chars={'a','b','c','d'};
//从char[]中第1位开始取出2个字符
String c = new String(chars, 1, 2);
System.out.println(c);//bc
String常用方法


注意事项:
字符串 str 中字符的索引从0开始,范围为 0 到 str.length()-1
使用 indexOf 进行字符或字符串查找时,如果匹配返回位置索引;如果没有匹配结果,返回 -1
使用 substring(beginIndex , endIndex) 进行字符串截取时,包括 beginIndex 位置的字符,不包括 endIndex 位置的字符【[左闭,右开)左包含,右不包含】
length,length(),size()的区别
length:是数组的一个属性,获取数组的长度
length():是字符串或者其他类的方法,获取字符长度
size():是集合类或者其他类的方法,获取集合中的数据量(个数)
int[] i={1,2,3,4};
System.out.println(i.length);//4
String s = "xiaoming";
System.out.println(s.length());//8
List list = new ArrayList();
list.add("1");
System.out.println(list.size());//1
Map map=new HashMap();
map.put(0,"map");
System.out.println(map.size());//1
返回结果为boolean类型的方法
boolean isEmpty():判断字符串是否为空。
boolean equals(Object obj):将此字符串的内容与指定的对象比较,区分大小写。
boolean equalsIgnoreCase(String str):将此String 与另一个String 比较,忽略大小写。
boolean contains(String str):判断字符串中是否包含方法传入的字符串。
boolean startsWith(String str):判断字符串是否以某个指定的字符串开头。
boolean endsWith(String str):判断字符串是否以某个指定的字符串结尾。
boolean isEmpty():判断字符串是否为空。
String xx=""与Sting xx=null的内存分析

String replace(char old,char new) : 替换功能。
String replace(String old,String new).替换功能。
String trim():去除字符串空格。
int compareTo(String str) : 按字典顺序比较两个字符串。
int compareToIgnoreCase(String str):按字典顺序比较两个字符串,忽略大小写。
public String[] split(String regex):分隔字符串成字符数组。
StringBuffer和StringBuilder
String在频繁拼接的场景是不推荐使用,因为这种情况下会在方法区中开辟很多空间,浪费资源,面对这种情况我可以使用StringBuffer或者StringBuilder来解决这种问题
StringBuffer
一个线程安全的,字符的可变序列。一个字符串缓冲区就像一 String,但是可以修改。在任何一个时间点,它包含一些特定的字符序列,但该序列的长度和内容可以通过某些方法调用。
通过null争论这类构造函数或方法会导致一个NullPointerException异常
StringBuilder。的StringBuilder类一般应优先使用StringBuilder,因为它支持所有相同的操作,但它的速度更快,因为它不进行同步。
构造方法
StringBuffer() 构造一个没有字符的字符串缓冲区,并构造了16个字符的初始容量。
StringBuffer(CharSequence seq) 构建一个包含指定的 CharSequence相同字符的字符串缓冲区。
StringBuffer(int capacity) 构造一个没有字符的字符串缓冲区,并构造指定的初始容量。
StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。
//StringBuffer无参构造创建了一个默认容量为16的字符数组
StringBuffer s1 = new StringBuffer();
//capacity() 获取StringBuffer容量
System.out.println(s1.capacity());//16
//构建一个包含指定的 `CharSequence`相同字符的字符串缓冲区
StringBuffer s2 = new StringBuffer('a');
System.out.println(s2.capacity()+":"+s2.toString());//97:
//构造一个初始化为指定字符串内容的字符串缓冲区。
StringBuffer s3 = new StringBuffer("hello");
System.out.println(s3.capacity()+":"+s3.toString());//21:hello
//构造一个没有字符的字符串缓冲区,并构造指定的初始容量
StringBuffer s4 = new StringBuffer(50);
System.out.println(s4.capacity()+":"+s4.toString());//50:
常用方法
String str="abc";
StringBuffer buffer = new StringBuffer();
buffer.append(str);
System.out.println(buffer);//abc
System.out.println(buffer.hashCode());//1163157884
//链式写法
buffer.append(1).append('a').append(new char[]{'a','b','d'});
System.out.println(buffer);//abc1aabd
//改变字符串不会开辟新的内存
System.out.println(buffer.hashCode());//1163157884
//从下标处插入字符,数组,字符串
buffer.insert(3, "insert插入");//abcinsert插入1aabd
System.out.println(buffer);
//移除指定一段下标数据(开始下标,结束下标)
buffer.delete(3,8);
System.out.println(buffer);//abct插入1aabd
//移除某一个下标的值
buffer.deleteCharAt(3);
System.out.println(buffer);//abc插入1aabd
//替换字符(开始下标,替换几个字符,替换值)
buffer.replace(0,3,"ABC");
System.out.println(buffer);//ABC插入1aabd
//颠倒字符
buffer.reverse();
System.out.println(buffer);//dbaa1入插CBA
StringBuilder
一个可变的字符序列。这个类提供了一个API兼容 StringBuffer,但无法保证同步。本课程是专为使用作为一个下降的替代(简易替换) StringBuffer在地方的字符串缓冲区被一个线程使用(一般情况下)。在可能的情况下,建议优先使用这StringBuilder, 它比StringBuffer更快。
StringBuffer和StringBuilder中的API都是相同的
String、StringBuffer、StringBuilder的区别
String:线程不安全,一旦在方法区创建就不能被更改,可以被多个引用共享,在做大量字符拼接时效率很低
StringBuffer、StringBuilder:可以改变字符内容,是一个字符串缓冲区,在拼接字符时不会开辟新的空间
StringBuffer:1.0开始 线程安全,效率低(Buffer:缓冲)
StringBuilder:1.5开始 线程不安全,效率高(单线程的话建议使用)(Builder:建造者)
包装类
每一个基本数据类型,都对应一个包装类,包装类都在 java.lang 包中,包装类提供了不同类型间进行转换的方法

Integer解析
//静态属性
//最大值 :2147483647
System.out.println(Integer.MAX_VALUE);
//最小值:-2147483648
System.out.println(Integer.MIN_VALUE);
//类代表原始类型的实例 int。
System.out.println(Integer.TYPE);
//构造方法
Integer integer = new Integer(6);
//传入非数字的字符串会报 NumberFormatException错误
Integer integer1 = new Integer("7");
类型转换
//String类型转为int
String s="3";
int i = Integer.parseInt(s);
int i1 = Integer.valueOf(s).intValue();
int i2 = new Integer(s).intValue();
//int类型转为String
int num=3;
String s1 = "" + 3;
String s2 = String.valueOf(num);
String s3 = Integer.toString(num);
装箱与拆箱
JDK1.5之后的特性
装箱:把基本类型转换成包装类,使其具有对象的性质,又可分为手动装箱和自动装箱
int j=10;//定义一个int基本类型值
Integer x=new Integer(j);//手动装箱
Integer y=j;//自动装箱
拆箱:和装箱相反,把包装类对象转换成基本类型的值,又可分为手动拆箱和自动拆箱
Integer j=new Integer(8);
int m=j.intValue();//手动拆箱为int类型
int n=j;//自动拆箱为int类型
Math类
这类 Math包含用于执行基本的数字运算等基本指数、对数、平方根法、三角函数。
Math方法
public static int abs(int a)//求绝对值
public static double sqrt(double a) // 开根号
public static double cceil(double a)//向上取整
public static double floor(double a)//向下取整
public static int max(int a,int b)//求最大值
public static int min(int a,int b)// 求最小值
public static double pow (double a,double b)//求a的b次幂
public static double random() //生成随机数
public static int round(float a)//四舍五入
//取0-99随机数
int v = (int) (Math.random() * 99);
System.out.println(v);
//获取20-30之间的随整数
int random = random(20, 30);
System.out.println(random);
public static int random(int start,int end){
return (int)(Math.random()*(end-start+1)+start);
Random工具类
此类用于生成随机数流在Java.utill包下面实现了 Serializable接口。
Serializable:Java给你提供一种应该比你自己的好的保存对象状态的机制,那就是序列化。序列化给我们提供了一种技术,用于保存对象的变量。以便于传输。
Random r=new Random();
System.out.println(r.nextDouble());//获取的是0.1-1.0之间的随机数
System.out.println(r.nextInt());//获取的是int最大值与最小值之间的随机数
System.out.println(r.nextLong());
System.out.println(r.nextInt(10));//获取的是0-10之间的随机数
System类
System类包含一些有用的类的字段和方法。它不能被实例化。
由System类提供的设施包括标准输入、标准输出和错误输出流;访问外部定义的属性和环境变量;加载文件和库的方法;和一种快速复制数组的一部分的实用方法。
//currentTimeMillis()返回当前时间以毫秒为单位。
long l = System.currentTimeMillis();//1640512311035
System.out.println(l);
Date date = new Date(l);
System.out.println(date);//Sun Dec 26 17:51:51 CST 2021
//终止当前正在运行的java虚拟机。后面代码将不再运行
System.exit(1);
//getProperties()确定当前系统属性。
Properties properties = System.getProperties();
System.out.println(properties.getProperty("java.version"));//1.8.0_31
// getProperties("java.version")获取指定键的系统属性
System.out.println(System.getProperty("java.version"));//1.8.0_31
//getSecurityManager()获取系统安全接口。
System.out.println(System.getSecurityManager());
BigInteger类
用于超出int存储范围值的计算
//最大值+30超出了int存储范围,打印出来为负数
Integer a=Integer.MAX_VALUE+30;
System.out.println(String.valueOf(a));//-2147483619
BigInteger bigInteger = new BigInteger(Integer.toString(Integer.MAX_VALUE));
System.out.println(bigInteger);//2147483647
//BigInteger调用add()将最大值加1
BigInteger bigIntegers = bigInteger.add(new BigInteger("1"));
System.out.println(bigIntegers);//2147483648
System.out.println(bigIntegers.longValue());//2147483648
System.out.println(bigIntegers.intValue());//-2147483648
System.out.println(bigIntegers.toString());//2147483648
BigDecimal类
double和float计算的是容易丢失精度,所以使用BigDecimal类来处理。
BigDecimal bigDecimal1 = new BigDecimal("0.08");
BigDecimal bigDecimal2 = new BigDecimal("0.01");
System.out.println(bigDecimal1.add(bigDecimal2));//加 0.09
System.out.println(bigDecimal1.multiply(bigDecimal2));//乘 0.0008
//注意:如果除不尽程序会报错。需要做四舍五入模式(RoundingMode HALF_UP)操作
System.out.println(bigDecimal1.divide(bigDecimal2));//除 8
System.out.println(bigDecimal1.subtract(bigDecimal2));//减 0.07
Date类
在java.util包下,表示时间,精确到毫秒
System.out.println(new Date());//Sun Dec 26 18:39:06 CST 2021
System.out.println(new Date(1231223423l));//Thu Jan 15 14:00:23 CST 1970
java.util.Date
就是在除了SQL语句的情况下面使用
表示时间的类,我们通常格式化或者得到当前时间
一般的环境下都行!
util.Date是sql.Date的父类
java.sql.Date
是针对SQL语句使用的,它只包含日期而没有时间部分
读写数据库时间字段的使用
主要是用于sql中的!
它都有getTime方法返回毫秒数,自然就可以直接构建
java.util.Date d = new java.util.Date(sqlDate.getTime());
SimpleDateFormat类
在java.text.SimpleDateFormat下继承了DateFormat类。是格式和语言环境敏感的方式解析一个类的具体日期。可以格式化(日期→文本),分析(文本→日期),和归一化。
使用 format() 方法将日期转换为指定格式的文本
使用 parse() 方法将文本转换为日期
Date date = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
//指定格式输出日期
System.out.println(simpleDateFormat.format(date));//21-12-26 下午6:47 默认
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(dateFormat.format(date));//2021-12-26 18:55:19
SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(dateFormat1.format(date));//2021/12/26 18:55:50
//字符串转Date
String dateStr="2021-12-26 18:55:19";
Date parseDate = dateFormat.parse(dateStr);
System.out.println(parseDate);//Sun Dec 26 18:55:19 CST 2021
Date类与SimpleDateFormat区别
调用 SimpleDateFormat 对象的 parse() 方法时可能会出现转换异常,即 ParseException ,因此需要进行异常处理
使用 Date 类时需要导入 java.util 包,使用 SimpleDateFormat 时需要导入 java.text 包
Calendar类
仅推荐使用 Calendar 类进行时间和日期加减周的处理。
java.util.Calendar 类是一个抽象类(不能被实例化new),可以通过调用 getInstance() 静态方法获取一个 Calendar 对象,此对象已由当前日期时间初始化,即默认代表当前时间,如 Calendar c = Calendar.getInstance();
//调用 Calendar 类的 getInstance() 方法获取一个实例,然后通过调用 get() 方法获取日期时间信息,参数为需要获得的字段的值, Calendar.Year 等为 Calendar 类中定义的静态常量。
Calendar c = Calendar.getInstance();//创建对象
int year=c.get(Calendar.YEAR);//年
int month=c.get(Calendar.MONTH)+1;//0表示1月。所以加1
int day=c.get(Calendar.DATE);//日
int hour=c.get(Calendar.HOUR_OF_DAY );//小时
int minute=c.get(Calendar.MINUTE);//分钟
int second=c.get(Calendar.SECOND);//秒
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);//这周第几天
int hourOfDay = c.get(Calendar.HOUR_OF_DAY);//今天的第几个小时
Calendar 和 Date 的转换
Calendar 类提供了 getTime() 方法,用来获取 Date 对象,完成 Calendar 和 Date 的转换,还可通过 getTimeInMillis() 方法,获取此 Calendar 的时间值,以毫秒为单位。
Calendar c = Calendar.getInstance();//创建对象
Date date=c.getTime();//转化为Date()对象
Long time=c.getTimeInMillis();//获取当前毫秒数
Calendar Date SimpleDateFormat 综合使用
// 创建Calendar对象
Calendar c = Calendar.getInstance();
int today=c.get(Calendar.DATE);
System.out.println("当前日期todate:" + today);//当前日期todate:26
// 将Calendar对象转换为Date对象
Date date = c.getTime();
System.out.println("当前时间date:" + date);//当前时间date:Sun Dec 26 19:16:45 CST 2021
// 创建SimpleDateFormat对象,指定目标格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 将日期转换为指定格式的字符串
String now = sdf.format(date);
System.out.println("当前时间now:" + now);//当前时间now:2021-12-26 19:16:45