文章目录
- Java基础(3)之常用API
- Object类
- toString()方法
- equals(Object o)方法
- clone() 方法
- Objects类
- 基本类型包装类
- 创建包装类对象及其特性
- 包装类数据类型转换
- 字符串操作类
- StringBuilder与StringBuffer类
- StringJoiner类
- Math类
- System类
- Runtime类
- BigDecimal类
- 日期时间类
- JDK8以后的时间类(推荐)
- LocalDate类(年月日),LocalTime类(时分秒),LocalDateTime类(年月日时分秒)
- LocalDate的常用API(都是处理年、月、日、星期相关的)。
- LocalTime的常用API (都是处理时、分、秒、纳秒相关的)。
- LocalDateTime的常用API(可以处理年、月、日、星期、时、分、秒、纳秒等信息)
- 时区时间类ZoneId与ZonedDateTime
- ZoneId 时区的常见方法
- ZonedDateTime带时区时间的常见方法
- Instant类
- DateTimeFormater类(格式化器)
- Period类与Duration类
- Period类
- Duration类
- JDK8以前的时间类
- Date类
- SimpleDateFormat类
- Calendar类
- Arrays类
- Lambda表达式
- Lambda表达式省略规则
- 方法引用
- 静态方法引用
- 实例方法引用
- 特定类型的方法引用
- 构造器引用
Java基础(3)之常用API
API(Application Programming interface)
意思是应用程序编程接口,说人话就是Java帮我们写好的一些程序,如:类、方法等,我们直接拿过来用就可以解决一些问题。
“千里之行始于足下,多记、多查、多写代码、孰能生巧!”
Object类
Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。
常用的两个方法:
public String toString()
返回对象的字符串表示形式。默认的格式是:“包名.类名@哈希值16进制”
【子类重写后,返回对象的属性值】
public boolean equals(Object o)
判断此对象与参数对象是否"相等"。默认比较对象的地址值,和"=="没有区别
【子类重写后,比较对象的属性值】
toString()方法
public String toString()调用toString()方法可以返回对象的字符串表示形式。默认的格式是:“包名.类名@哈希值16进制”
所有类默认继承obejct类后,都会继承这个toString()方法
子类重写toString()方法,那么我们就可以返回对象的属性值
public class Student{private String name;private int age;public Student(String name, int age){this.name=name;this.age=age;}@Overridepublic String toString(){return "Student{name=‘"+name+"’, age="+age+"}";} }
equals(Object o)方法
public boolean equals(Object o)判断此对象与参数对象是否"相等"
equals默认也是
比较对象的地址
,和"=="没有区别public class Test{public static void main(String[] args){Student s1 = new Student("赵薇",23);Student s2 = new Student("赵薇",23);//equals本身也是比较对象的地址,和"=="没有区别System.out.println(s1.equals(s2)); //false//"=="比较对象的地址System.out.println(s1==s2); //false} }
不过我们子类继承后可以重写
public class Student{private String name;private int age;public Student(String name, int age){this.name=name;this.age=age;}@Overridepublic String toString(){return "Student{name=‘"+name+"’, age="+age+"}";}//重写equals方法,按照对象的属性值进行比较@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;} }
clone() 方法
某一个对象调用这个方法,这个方法会复制一个一模一样的新对象,并返回。
public Object clone()克隆当前对象,返回一个新对象
想要调用clone()方法,必须让被克隆的类实现
Cloneable接口
public class User implements Cloneable{private String id; //编号private String username; //用户名private String password; //密码private double[] scores; //分数public User() {}public User(String id, String username, String password, double[] scores) {this.id = id;this.username = username;this.password = password;this.scores = scores;}@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();} }
上面演示的克隆方式,是一种浅克隆的方法,浅克隆的意思:拷贝出来的对象封装的数据与原对象封装的数据一模一样(引用类型拷贝的是地址值)。就是scores数组的地址值都是一样的
那
深拷贝
怎么办呢?public class User implements Cloneable{private String id; //编号private String username; //用户名private String password; //密码private double[] scores; //分数public User() {}public User(String id, String username, String password, double[] scores) {this.id = id;this.username = username;this.password = password;this.scores = scores;}//...get和set...方法自己加上@Overrideprotected Object clone() throws CloneNotSupportedException {//先克隆得到一个新对象User u = (User) super.clone();//再将新对象中的引用类型数据,再次克隆u.scores = u.scores.clone();return u;} }
Objects类
Objects是一个工具类,提供了一些方法可以对任意对象进行操作。
public class Test{public static void main(String[] args){String s1 = null;String s2 = "itheima";//这里会出现NullPointerException异常,调用者不能为nullSystem.out.println(s1.equals(s2));//此时不会有NullPointerException异常,底层会自动先判断空System.out.println(Objects.equals(s1,s2));//判断对象是否为null,等价于==System.out.println(Objects.isNull(s1)); //trueSystem.out.println(s1==null); //true//判断对象是否不为null,等价于!=System.out.println(Objects.nonNull(s2)); //trueSystem.out.println(s2!=null); //true}
}
基本类型包装类
为什么要学习包装类呢?因为在Java中有一句很经典的话,万物皆对象。Java中的8种基本数据类型还不是对象,所以要把它们变成对象,变成对象之后,可以提供一些方法对数据进行操作。
创建包装类对象及其特性
以Integer为例,其它类似
//1.创建Integer对象,封装基本类型数据10 Integer a = new Integer(10);//2.使用Integer类的静态方法valueOf(数据) Integer b = Integer.valueOf(10);
自动装箱特性
//3.还有一种自动装箱的写法(意思就是自动将基本类型转换为引用类型) Integer c = 10;
自动拆箱特性
//4.有装箱肯定还有拆箱(意思就是自动将引用类型转换为基本类型) int d = c;
装箱和拆箱在使用集合时就有体现
ArrayList<Integer> list = new ArrayList<>(); //添加的元素是基本类型,实际上会自动装箱为Integer类型 list.add(100); //获取元素时,会将Integer类型自动拆箱为int类型 int e = list.get(0);
包装类数据类型转换
开发中,经常使用包装类对字符串和基本类型数据进行相互转换。
- 把字符串转换为数值型数据:
包装类.parseXxx(字符串)
public static int parseInt(String s)把字符串转换为基本数据类型
- 将数值型数据转换为字符串:包装类.valueOf(数据);
public static String valueOf(int a)把基本类型数据转换为字符串
//1.字符串转换为数值型数据 String ageStr = "29"; int age1 = Integer.parseInt(ageStr);String scoreStr = 3.14; double score = Double.prarseDouble(scoreStr);//2.整数转换为字符串,以下几种方式都可以(挑中你喜欢的记一下) Integer a = 23; String s1 = Integer.toString(a); String s2 = a.toString(); String s3 = a+""; String s4 = String.valueOf(a);
字符串操作类
StringBuilder与StringBuffer类
StringBuffer
的用法与StringBuilder
是一模一样的但StringBuilder
是线程不安全的StringBuffer
是线程安全的对于字符串相关的操作,如频繁的拼接、修改等,建议用
StringBuidler
如果操作字符串较少,或者不需要操作,以及定义字符串时,则用
String
。
StringBuilder
代表可变字符串对象,相当于是一个容器,它里面的字符串是可以改变的,就是用来操作字符串的。- 好处:
StringBuilder
比String
更合适做字符串的修改操作,效率更高,代码也更加简洁。
构造器 说明 public StringBuilder() 创建一个空白的可变的字符串对象,不包含任何内容 public StringBuilder(String str) 创建一个指定字符串内容的可变字符串对象
方法名称 说明 public StringBuilder append(任意类型) 添加数据并返回StringBuilder对象本身 public StringBuilder reverse() 将对象的内容反转 public int length() 返回对象内容长度 public String toString() 通过toString()就可以实现把StringBuilder转换为String
StringBuilder
代表可变字符串对象,相当于是一个容器,它里面的字符串是可以改变
的,就是用来操作字符串的。- 好处:
StringBuilder比String更合适做字符串的修改操作
,效率更高,代码也更加简洁。
1.可以直接根据字符串String对象创建StringBuilder对象 StringBuilder sb = new StringBuilder("itehima"); 2.当然StringBuilder对象也可以转换为String对象 String s = sb.toString();
3.可以拼接内容 sb.append(12); sb.append("黑马"); sb.append(true); 4.也支持下方操作 sb.append(666).append("黑马2").append(666);
5.反转操作 sb.reverse(); System.out.println(sb); //打印:6662马黑666马黑21
6.返回字符串的长度 System.out.println(sb.length());
-
方法作用:将int数组转换为指定格式的字符串
-
public static String getArrayData(int[] arr){//1.判断数组是否为nullif(arr==null){return null;}//2.如果数组不为null,再遍历,并拼接数组中的元素StringBuilder sb = new StringBuilder("[");for(int i=0; i<arr.length; i++){if(i==arr.legnth-1){sb.append(arr[i]).append("]");;}else{sb.append(arr[i]).append(",");}}//3、把StirngBuilder转换为String,并返回。return sb.toString();}
StringJoiner类
构造器 | 说明 |
---|---|
public StringJoiner (间隔符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号 |
public StringJoiner (间隔符号,开始符号,结束符号) | 创建一个StringJoiner对象,指定拼接时的间隔符号、开始符号、结束符号 |
方法名称 | 说明 |
---|---|
public StringJoiner add (添加的内容) | 添加数据,并返回对象本身 |
public int length() | 返回长度 ( 字符出现的个数) |
public String toString() | 返回一个字符串(该字符串就是拼接之后的结果) |
StringJoiner
号称是拼接神器
,不仅效率高,而且代码简洁。
-
示例
-
public class Test{public static void main(String[] args){StringJoiner s = new StringJoiner(",");s.add("java1");s.add("java2");s.add("java3");System.out.println(s); //结果为: java1,java2,java3//参数1:间隔符//参数2:开头//参数3:结尾StringJoiner s1 = new StringJoiner(",","[","]");s1.add("java1");s1.add("java2");s1.add("java3");System.out.println(s1); //结果为: [java1,java2,java3]} }
-
重写上方将int数组转换为指定格式的字符串
-
public class Test{public static void main(String[] args){String str = getArrayData( new int[]{11,22,33});System.out.println(str);}//方法作用:将int数组转换为指定格式的字符串public static String getArrayData(int[] arr){//1.判断数组是否为nullif(arr==null){return null;}//2.如果数组不为null,再遍历,并拼接数组中的元素StringJoiner s = new StringJoiner(", ","[","]");for(int i=0; i<arr.length; i++){//加""是因为add方法的参数要的是String类型s.add(String.valueOf(arr[i]));}//3、把StringJoiner转换为String,并返回。return s.toString();} }
-
Math类
代表数学,是一个工具类,里面提供的都是对数据进行操作的一些静态方法。
方法名 说明 public static int abs(int a) 获取参数绝对值 public static double ceil(double a) 向上取整 public static double floor(double a) 向下取整 public static int round(float a) 四舍五入 public static int max(int a,int b) 获取两个int值中的较大值 public static double pow(double a,double b) 返回a的b次幂的值 public static double random() 返回值为double的随机值,范围[0.0,1.0)
示例:
public class MathTest {public static void main(String[] args) {// 目标:了解下Math类提供的常见方法。// 1、public static int abs(int a):取绝对值(拿到的结果一定是正数)// public static double abs(double a)System.out.println(Math.abs(-12)); // 12System.out.println(Math.abs(123)); // 123System.out.println(Math.abs(-3.14)); // 3.14// 2、public static double ceil(double a): 向上取整System.out.println(Math.ceil(4.0000001)); // 5.0System.out.println(Math.ceil(4.0)); // 4.0// 3、public static double floor(double a): 向下取整System.out.println(Math.floor(4.999999)); // 4.0System.out.println(Math.floor(4.0)); // 4.0// 4、public static long round(double a):四舍五入System.out.println(Math.round(3.4999)); // 3System.out.println(Math.round(3.50001)); // 4// 5、public static int max(int a, int b):取较大值// public static int min(int a, int b):取较小值System.out.println(Math.max(10, 20)); // 20System.out.println(Math.min(10, 20)); // 10// 6、 public static double pow(double a, double b):取次方System.out.println(Math.pow(2, 3)); // 2的3次方 8.0System.out.println(Math.pow(3, 2)); // 3的2次方 9.0// 7、public static double random(): 取随机数 [0.0 , 1.0) (包前不包后)System.out.println(Math.random());} }
System类
System代表程序所在的系统,也是一个工具类
方法名 说明 public static void exit(int status) 终止当前运行的Java虚拟机。 public static long currentTimeMillis() 返回当前系统的 时间毫秒值
形式
- 时间毫秒值
- 指的是从1970年1月1日
00:00:00
走到此刻的总的毫秒数,应该是很大的。1s = 1000ms。
/*** 目标:了解下System类的常见方法。*/ public class SystemTest {public static void main(String[] args) {// 1、public static void exit(int status):// 终止当前运行的Java虚拟机。// 该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。System.exit(0); // 人为的终止虚拟机。(不要使用)// 2、public static long currentTimeMillis():// 获取当前系统的时间// 返回的是long类型的时间毫秒值:指的是从1970-1-1 0:0:0开始走到此刻的总的毫秒值,1s = 1000mslong 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");} }
Runtime类
代表程序所在的运行环境。
Runtime是一个单例类。
方法名 说明 public static Runtime getRuntime() 返回与当前Java应用程序关联的运行时对象 public void exit(int status) 终止当前运行的虚拟机 public int availableProcessors() 返回Java虚拟机可用的处理器数。 public long totalMemory() 返回Java虚拟机中的内存总量 public long freeMemory() 返回Java虚拟机中的可用内存 public Process exec(String command) 启动某个程序,并返回代表该程序的对象
/*** 目标:了解下Runtime的几个常见方法。*/ public class RuntimeTest {public static void main(String[] args) throws IOException, InterruptedException {// 1、public static Runtime getRuntime() 返回与当前Java应用程序关联的运行时对象。Runtime r = Runtime.getRuntime();// 2、public void exit(int status) 终止当前运行的虚拟机,该参数用作状态代码; 按照惯例,非零状态代码表示异常终止。// r.exit(0);// 3、public int availableProcessors(): 获取虚拟机能够使用的处理器数。System.out.println(r.availableProcessors());// 4、public long totalMemory() 返回Java虚拟机中的内存总量。System.out.println(r.totalMemory()/1024.0/1024.0 + "MB"); // 1024 = 1K 1024 * 1024 = 1M// 5、public long freeMemory() 返回Java虚拟机中的可用内存量System.out.println(r.freeMemory()/1024.0/1024.0 + "MB");// 6、public Process exec(String command) 启动某个程序,并返回代表该程序的对象。// r.exec("D:\\soft\\XMind\\XMind.exe");Process p = r.exec("QQ");Thread.sleep(5000); // 让程序在这里暂停5s后继续往下走!!p.destroy(); // 销毁!关闭程序!} }
BigDecimal类
用于解决浮点型运算时,出现结果失真的问题。
public static void main(String[] args) { // 浮点型运算时, 直接+ - * / 可能会出现运算结果失真System.out.println(0.1 + 0.2);System.out.println(1.0 - 0.32);System.out.println(1.015 * 100);System.out.println(1.301 / 100); }
构造器 说明 public BigDecimal(double val) 注意:不推荐使用这个 将 double转换为 BigDecimal public BigDecimal(String val) 把String转成BigDecimal
方法名 说明 public static BigDecimal valueOf(double val) 转换一个 double成 BigDecimal public BigDecimal add(BigDecimal b) 加法 public BigDecimal subtract(BigDecimal b) 减法 public BigDecimal multiply(BigDecimal b) 乘法 public BigDecimal divide(BigDecimal b) 除法 public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) 除法、可以控制精确到小数几位 public double doubleValue() 将BigDecimal转换为double
应该如何把浮点型转换成
BigDecimal
的对象?
BigDecimal b1 = BigDecimal.valueOf(0.1)
public class Test2 {public static void main(String[] args) {// 目标:掌握BigDecimal进行精确运算的方案。double a = 0.1;double b = 0.2;// 1、把浮点型数据封装成BigDecimal对象,再来参与运算。// a、public BigDecimal(double val) 得到的BigDecimal对象是无法精确计算浮点型数据的。 注意:不推荐使用这个,// b、public BigDecimal(String val) 得到的BigDecimal对象是可以精确计算浮点型数据的。 可以使用。// c、public static BigDecimal valueOf(double val): 通过这个静态方法得到的BigDecimal对象是可以精确运算的。是最好的方案。BigDecimal a1 = BigDecimal.valueOf(a);BigDecimal b1 = BigDecimal.valueOf(b);// 2、public BigDecimal add(BigDecimal augend): 加法BigDecimal c1 = a1.add(b1);System.out.println(c1);// 3、public BigDecimal subtract(BigDecimal augend): 减法BigDecimal c2 = a1.subtract(b1);System.out.println(c2);// 4、public BigDecimal multiply(BigDecimal augend): 乘法BigDecimal c3 = a1.multiply(b1);System.out.println(c3); // 5、public BigDecimal divide(BigDecimal b): 除法BigDecimal c4 = a1.divide(b1);System.out.println(c4);// BigDecimal d1 = BigDecimal.valueOf(0.1); // BigDecimal d2 = BigDecimal.valueOf(0.3); // BigDecimal d3 = d1.divide(d2); // System.out.println(d3);// 6、public BigDecimal divide(另一个BigDecimal对象,精确几位,舍入模式) : 除法,可以设置精确几位。BigDecimal d1 = BigDecimal.valueOf(0.1);BigDecimal d2 = BigDecimal.valueOf(0.3);BigDecimal d3 = d1.divide(d2, 2, RoundingMode.HALF_UP); // 0.33System.out.println(d3);// 7、public double doubleValue() : 把BigDecimal对象又转换成double类型的数据。//print(d3);//print(c1);double db1 = d3.doubleValue();double db2 = c1.doubleValue();print(db1);print(db2);}public static void print(double a){System.out.println(a);} }
日期时间类
JDK8以后的时间类(推荐)
LocalDate类(年月日),LocalTime类(时分秒),LocalDateTime类(年月日时分秒)
LocalDate
:代表本地日期(年、月、日、星期)
LocalTime
:代表本地时间(时、分、秒、纳秒)
LocalDateTime
:代表本地日期、时间(年、月、日、星期、时、分、秒、纳秒)
获取对象的方式:
LocalDate的常用API(都是处理年、月、日、星期相关的)。
方法名 说明 public int geYear() 获取年 public int getMonthValue() 获取月份(1-12) public int getDayOfMonth() 获取日 public int getDayOfYear() 获取当前是一年中的第几天 Public DayOfWeek getDayOfWeek() 获取星期几:ld.getDayOfWeek().getValue()
方法名 说明 withYear、withMonth、withDayOfMonth、withDayOfYear 直接修改某个信息,返回新日期对象 plusYears、plusMonths、plusDays、plusWeeks 把某个信息加多少,返回新日期对象 minusYears、minusMonths、minusDays,minusWeeks 把某个信息减多少,返回新日期对象 equals isBefore isAfter 判断两个日期对象,是否相等,在前还是在后 示例:
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(); // 月(1-12)int day = ld.getDayOfMonth(); // 日int dayOfYear = ld.getDayOfYear(); // 一年中的第几天int dayOfWeek = ld.getDayOfWeek().getValue(); // 星期几System.out.println(year);System.out.println(day);System.out.println(dayOfWeek);// 2、直接修改某个信息: withYear、withMonth、withDayOfMonth、withDayOfYearLocalDate 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、plusWeeksLocalDate ld4 = ld.plusYears(2);LocalDate ld5 = ld.plusMonths(2);// 4、把某个信息减多少:minusYears、minusMonths、minusDays、minusWeeksLocalDate 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 isAfterSystem.out.println(ld8.equals(ld9));// trueSystem.out.println(ld8.isAfter(ld)); // trueSystem.out.println(ld8.isBefore(ld)); // false} }
LocalTime的常用API (都是处理时、分、秒、纳秒相关的)。
方法名 说明 public int getHour() 获取小时 public int getMinute() 获取分 public int getSecond() 获取秒 public int getNano() 获取纳秒
方法名 说明 withHour、withMinute、withSecond、withNano 修改时间,返回新时间对象 plusHours、plusMinutes、plusSeconds、plusNanos 把某个信息加多少,返回新时间对象 minusHours、minusMinutes、minusSeconds、minusNanos 把某个信息减多少,返回新时间对象 equals isBefore isAfter 判断2个时间对象,是否相等,在前还是在后 示例:
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、withNanoLocalTime lt3 = lt.withHour(10);LocalTime lt4 = lt.withMinute(10);LocalTime lt5 = lt.withSecond(10);LocalTime lt6 = lt.withNano(10);// 3、加多少:plusHours、plusMinutes、plusSeconds、plusNanosLocalTime lt7 = lt.plusHours(10);LocalTime lt8 = lt.plusMinutes(10);LocalTime lt9 = lt.plusSeconds(10);LocalTime lt10 = lt.plusNanos(10);// 4、减多少:minusHours、minusMinutes、minusSeconds、minusNanosLocalTime 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 isAfterSystem.out.println(lt15.equals(lt16)); // trueSystem.out.println(lt15.isAfter(lt)); // falseSystem.out.println(lt15.isBefore(lt)); // true} }
LocalDateTime的常用API(可以处理年、月、日、星期、时、分、秒、纳秒等信息)
方法名 说明 getYear、getMonthValue、getDayOfMonth、getDayOfYeargetDayOfWeek、getHour、getMinute、getSecond、getNano 获取年月日、时分秒、纳秒等 withYear、withMonth、withDayOfMonth、withDayOfYearwithHour、withMinute、withSecond、withNano 修改某个信息,返回新日期时间对象 plusYears、plusMonths、plusDays、plusWeeksplusHours、plusMinutes、plusSeconds、plusNanos 把某个信息加多少,返回新日期时间对象 minusYears、minusMonths、minusDays、minusWeeksminusHours、minusMinutes、minusSeconds、minusNanos 把某个信息减多少,返回新日期时间对象 equals isBefore isAfter 判断2个时间对象,是否相等,在前还是在后 示例:
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 withNanoLocalDateTime ldt2 = ldt.withYear(2029);LocalDateTime ldt3 = ldt.withMinute(59);// 3、加多少:// plusYears plusMonths plusDays plusWeeks plusHours plusMinutes plusSeconds plusNanosLocalDateTime ldt4 = ldt.plusYears(2);LocalDateTime ldt5 = ldt.plusMinutes(3);// 4、减多少:// minusDays minusYears minusMonths minusWeeks minusHours minusMinutes minusSeconds minusNanosLocalDateTime 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)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、isAfterSystem.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);} }
LocalDateTime
的转换成LocalDate、LocalTime
方法名 说明 public LocalDate toLocalDate() 转换成一个LocalDate对象 public LocalTime toLocalTime() 转换成一个LocalTime对象
时区时间类ZoneId与ZonedDateTime
由于世界各个国家与地区的经度不同,各地区的时间也有所不同,因此会划分为不同的时区。
ZoneId 时区的常见方法
方法名 说明 public static Set getAvailableZoneIds() 获取Java中支持的所有时区 public static ZoneId systemDefault() 获取系统默认时区 public static ZoneId of(String zoneId) 获取一个指定时区
ZonedDateTime带时区时间的常见方法
方法名 说明 public static ZonedDateTime now() 获取当前时区的ZonedDateTime对象 public static ZonedDateTime now(ZoneId zone) 获取指定时区的ZonedDateTime对象 getYear、getMonthValue、getDayOfMonth、getDayOfYeargetDayOfWeek、getHour、getMinute、getSecond、getNano 获取年月日、时分秒、纳秒等 public ZonedDateTime withXxx(时间) 修改时间系列的方法 public ZonedDateTime minusXxx(时间) 减少时间系列的方法 public ZonedDateTime plusXxx(时间) 增加时间系列的方法
示例:
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支持的全部时区IdSystem.out.println(ZoneId.getAvailableZoneIds());// public static ZoneId of(String zoneId) : 把某个时区id封装成ZoneId对象。ZoneId zoneId1 = ZoneId.of("America/New_York");// 2、ZonedDateTime:带时区的时间。// public static ZonedDateTime now(ZoneId zone): 获取某个时区的ZonedDateTime对象。ZonedDateTime now = ZonedDateTime.now(zoneId1);System.out.println(now);// 世界标准时间了ZonedDateTime now1 = ZonedDateTime.now(Clock.systemUTC());System.out.println(now1);// public static ZonedDateTime now():获取系统默认时区的ZonedDateTime对象ZonedDateTime now2 = ZonedDateTime.now();System.out.println(now2);// Calendar instance = Calendar.getInstance(TimeZone.getTimeZone(zoneId1));} }
Instant类
-
作用:可以用来记录代码的执行时间,或用于记录用户操作某个事件的时间点。
-
传统的Date类,只能精确到毫秒,并且是可变对象;
新增的Instant类,可以精确到纳秒,并且是不可变对象,推荐用Instant代替Date。
通过获取Instant的对象可以拿到此刻的时间,该时间由两部分组成:从1970-01-01 00:00:00 开始走到此刻的总秒数+不够1秒的纳秒数。
- 该类提供的方法如下图所示,可以用来获取当前时间,也可以对时间进行加、减、获取等操作。
示例:
/*** 目标:掌握Instant的使用。*/ public class Test5_Instant {public static void main(String[] args) {// 1、创建Instant的对象,获取此刻时间信息Instant now = Instant.now(); // 不可变对象// 2、获取总秒数long second = now.getEpochSecond();System.out.println(second);// 3、不够1秒的纳秒数int nano = now.getNano();System.out.println(nano);System.out.println(now);Instant instant = now.plusNanos(111);// Instant对象的作用:做代码的性能分析,或者记录用户的操作时间点Instant now1 = Instant.now();// 代码执行。。。。Instant now2 = Instant.now();LocalDateTime l = LocalDateTime.now();} }
DateTimeFormater类(格式化器)
示例:
/*** 目标:掌握JDK 8新增的DateTimeFormatter格式化器的用法。*/ public class Test6_DateTimeFormatter {public static void main(String[] args) {// 1、创建一个日期时间格式化器对象出来。DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");// 2、对时间进行格式化LocalDateTime now = LocalDateTime.now();System.out.println(now);String rs = formatter.format(now); // 正向格式化System.out.println(rs);// 3、格式化时间,其实还有一种方案。String rs2 = now.format(formatter); // 反向格式化System.out.println(rs2);// 4、解析时间:解析时间一般使用LocalDateTime提供的解析方法来解析。String dateStr = "2029年12月12日 12:12:11";LocalDateTime ldt = LocalDateTime.parse(dateStr, formatter);System.out.println(ldt);} }
Period类与Duration类
Period用来计算日期间隔(年、月、日),Duration用来计算时间间隔(时、分、秒、纳秒)
Period类
只能两个计算LocalDate对象之间的间隔
示例:
/*** 目标:掌握Period的作用:计算机两个日期相差的年数,月数、天数。*/ public class Test7_Period {public static void main(String[] args) {LocalDate start = LocalDate.of(2029, 8, 10);LocalDate end = LocalDate.of(2029, 12, 15);// 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());} }
Duration类
可以用于计算两个时间对象相差的天数、小时数、分数、秒数、纳秒数;支持LocalTime、LocalDateTime、Instant等时间
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());// 间隔多少纳秒} }
JDK8以前的时间类
Date类
Date对象记录的时间是用毫秒值来表示的。Java语言规定,1970年1月1日0时0分0秒认为是时间的起点,此时记作0,那么1000(1秒=1000毫秒)就表示1970年1月1日0时0分1秒。
示例:
public class Test1Date {public static void main(String[] args) {// 目标:掌握Date日期类的使用。// 1、创建一个Date的对象:代表系统当前时间信息的。Date d = new Date();System.out.println(d);// 2、拿到时间毫秒值。long time = d.getTime();System.out.println(time);// 3、把时间毫秒值转换成日期对象: 2s之后的时间是多少。time += 2 * 1000;Date d2 = new Date(time);System.out.println(d2);// 4、直接把日期对象的时间通过setTime方法进行修改Date d3 = new Date();d3.setTime(time);System.out.println(d3);} }
SimpleDateFormat类
打印Date对象时,发现打印输出的日期格式我们并不喜欢,是不是?接下来我们学习的
SimpleDateFormat
类就可以转换Date对象表示日期时间的显示格式。
我们把Date对象转换为指定格式的日期字符串这个操作,叫做日期格式化,
反过来把指定格式的日期符串转换为Date对象的操作,叫做日期解析。
创建
SimpleDateFormat
对象时,在构造方法的参数位置传递日期格式,而日期格式是由一些特定的字母拼接而来的。我们需要记住常用的几种日期/时间格式
字母 表示含义 yyyy 年 MM 月 dd 日 HH 时 mm 分 ss 秒 SSS 毫秒"2022年12月12日" 的格式是 "yyyy年MM月dd日" "2022-12-12 12:12:12" 的格式是 "yyyy-MM-dd HH:mm:ss" 按照上面的格式可以任意拼接,但是字母不能写错
示例:
public class Test2SimpleDateFormat {public static void main(String[] args) throws ParseException {// 目标:掌握SimpleDateFormat的使用。// 1、准备一些时间Date d = new Date();System.out.println(d);long time = d.getTime();System.out.println(time);// 2、格式化日期对象,和时间 毫秒值。SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");String rs = sdf.format(d);String rs2 = sdf.format(time);System.out.println(rs);System.out.println(rs2);System.out.println("----------------------------------------------");// 目标:掌握SimpleDateFormat解析字符串时间 成为日期对象。String dateStr = "2022-12-12 12:12:11";// 1、创建简单日期格式化对象 , 指定的时间格式必须与被解析的时间格式一模一样,否则程序会出bug.SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d2 = sdf2.parse(dateStr);System.out.println(d2);} }
public class Test3 {public static void main(String[] args) throws ParseException {// 目标:完成秒杀案例。// 1、把开始时间、结束时间、小贾下单时间、小皮下单时间拿到程序中来。String start = "2023年11月11日 0:0:0";String end = "2023年11月11日 0:10:0";String xj = "2023年11月11日 0:01:18";String xp = "2023年11月11日 0:10:57";// 2、把字符串的时间解析成日期对象。SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");Date startDt = sdf.parse(start);Date endDt = sdf.parse(end);Date xjDt = sdf.parse(xj);Date xpDt = sdf.parse(xp);// 3、开始判断小皮和小贾是否秒杀成功了。// 把日期对象转换成时间毫秒值来判断long startTime = startDt.getTime();long endTime = endDt.getTime();long xjTime = xjDt.getTime();long xpTime = xpDt.getTime();if(xjTime >= startTime && xjTime <= endTime){System.out.println("小贾您秒杀成功了~~");}else {System.out.println("小贾您秒杀失败了~~");}if(xpTime >= startTime && xpTime <= endTime){System.out.println("小皮您秒杀成功了~~");}else {System.out.println("小皮您秒杀失败了~~");}} }
Calendar类
Calendar类表示日历,它提供了一些比Date类更好用的方法。
因为Calendar类提供了方法可以直接对日历中的年、月、日、时、分、秒等进行运算。
public class Test4Calendar {public static void main(String[] args) {// 目标:掌握Calendar的使用和特点。// 1、得到系统此刻时间对应的日历对象。Calendar now = Calendar.getInstance();System.out.println(now);// 2、获取日历中的某个信息int year = now.get(Calendar.YEAR);System.out.println(year);int days = now.get(Calendar.DAY_OF_YEAR);System.out.println(days);// 3、拿到日历中记录的日期对象。Date d = now.getTime();System.out.println(d);// 4、拿到时间毫秒值long time = now.getTimeInMillis();System.out.println(time);// 5、修改日历中的某个信息now.set(Calendar.MONTH, 9); // 修改月份成为10月份。now.set(Calendar.DAY_OF_YEAR, 125); // 修改成一年中的第125天。System.out.println(now);// 6、为某个信息增加或者减少多少now.add(Calendar.DAY_OF_YEAR, 100);now.add(Calendar.DAY_OF_YEAR, -10);now.add(Calendar.DAY_OF_MONTH, 6);now.add(Calendar.HOUR, 12);now.set(2026, 11, 22);System.out.println(now);} }
Arrays类
用来操作数组的一个工具类。
Arrays并不是重点,但是我们通过Arrays这个类的学习有助于我们理解下一个知识点Lambda的学习。
示例:
/*** 目标:掌握Arrays类的常用方法。*/ public class ArraysTest1 {public static void main(String[] args) {// 1、public static String toString(类型[] arr): 返回数组的内容int[] arr = {10, 20, 30, 40, 50, 60};System.out.println(Arrays.toString(arr));// 2、public static 类型[] copyOfRange(类型[] arr, 起始索引, 结束索引) :拷贝数组(指定范围,包前不包后)int[] arr2 = Arrays.copyOfRange(arr, 1, 4);System.out.println(Arrays.toString(arr2));// 3、public static copyOf(类型[] arr, int newLength):拷贝数组,可以指定新数组的长度。int[] arr3 = Arrays.copyOf(arr, 10);System.out.println(Arrays.toString(arr3));// 4、public static setAll(double[] array, IntToDoubleFunction generator):把数组中的原数据改为新数据又存进去。double[] prices = {99.8, 128, 100};// 0 1 2// 把所有的价格都打八折,然后又存进去。Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;}});System.out.println(Arrays.toString(prices));// 5、public static void sort(类型[] arr):对数组进行排序(默认是升序排序)Arrays.sort(prices);System.out.println(Arrays.toString(prices));} }
如果数组中存储的元素类型是自定义的对象,如何排序呢?
1.让该对象的类实现Comparable(比较规则)接口,然后重写compareTo方法,自己来制定比较规则。
2.使用下面这个sort方法,创建Comparator比较器接口的匿名内部类对象,然后自己制定比较规则。
Student[] students = new Student[4]; students[0] = new Student("蜘蛛精", 169.5, 23); students[1] = new Student("紫霞", 163.8, 26); students[2] = new Student("紫霞", 163.8, 26); students[3] = new Student("至尊宝", 167.5, 24);
- **排序方式1:**让Student类实现Comparable接口,同时重写compareTo方法。Arrays的sort方法底层会根据compareTo方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下:
public class Student implements Comparable<Student>{private String name;private double height;private int age;//...get、set、空参数构造方法、有参数构造方法...自己补全// 指定比较规则// this o@Overridepublic int compareTo(Student o) {// 约定1:认为左边对象 大于 右边对象 请您返回正整数// 约定2:认为左边对象 小于 右边对象 请您返回负整数// 约定3:认为左边对象 等于 右边对象 请您一定返回0/* if(this.age > o.age){return 1;}else if(this.age < o.age){return -1;}return 0;*///上面的if语句,也可以简化为下面的一行代码return this.age - o.age; // 按照年龄升序排列// return o.age - this.age; // 按照年龄降序排列}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", height=" + height +", age=" + age +'}';} }
- **排序方式2:**在调用
Arrays.sort(数组,Comparator比较器);
时,除了传递数组之外,传递一个Comparator比较器对象。Arrays的sort方法底层会根据Comparator比较器对象的compare方法方法的返回值是正数、负数、还是0来确定谁大、谁小、谁相等。代码如下:public class ArraysTest2 {public static void main(String[] args) {// 目标:掌握如何对数组中的对象进行排序。Student[] students = new Student[4];students[0] = new Student("蜘蛛精", 169.5, 23);students[1] = new Student("紫霞", 163.8, 26);students[2] = new Student("紫霞", 163.8, 26);students[3] = new Student("至尊宝", 167.5, 24);// 2、public static <T> void sort(T[] arr, Comparator<? super T> c)// 参数一:需要排序的数组// 参数二:Comparator比较器对象(用来制定对象的比较规则)Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 制定比较规则了:左边对象 o1 右边对象 o2// 约定1:认为左边对象 大于 右边对象 请您返回正整数// 约定2:认为左边对象 小于 右边对象 请您返回负整数// 约定3:认为左边对象 等于 右边对象 请您一定返回0 // if(o1.getHeight() > o2.getHeight()){ // return 1; // }else if(o1.getHeight() < o2.getHeight()){ // return -1; // } // return 0; // 升序return Double.compare(o1.getHeight(), o2.getHeight()); // 升序// return Double.compare(o2.getHeight(), o1.getHeight()); // 降序}});System.out.println(Arrays.toString(students));} }
Lambda表达式
作用:用于简化匿名内部类代码的书写。
(被重写方法的形参列表) -> {被重写方法的方法体代码; }
在使用Lambda表达式之前,
必须先有一个接口,而且接口中
只能有一个抽象方法
。(注意:不能是抽象类,只能是接口)
public interface Swimming{void swim(); }
像这样的接口,我们称之为
函数式接口
,只有基于函数式接口的匿名内部类
才能被Lambda表达式
简化。
示例:
使用Lambda表达式,
简化匿名内部类书写
。//1.创建一个Swimming接口的匿名内部类对象Swimming s = new Swimming(){@Overridepublic void swim() {System.out.println("学生快乐的游泳~~~~");}};s.swim();
简化后:
//2.使用Lambda表达式对Swimming接口的匿名内部类进行简化Swimming s1 = () -> {System.out.println("学生快乐的游泳~~~~");};s1.swim();
Arrays类中Lambda的妙用:
//1.把所有元素*0.8: 先用匿名内部类写法 Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;} }); //2.把所有元素*0.8: 改用Lamdba表达式写法 Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8; });
//3.对数组中的元素按照年龄升序排列: 先用匿名内部类写法 Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序} }); //4.对数组中的元素按照年龄升序排列: 改用Lambda写法 Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序 });
Lambda表达式省略规则
Java觉得代码还不够简单,于是还提供了Lamdba表达式的
几种简化写法
Lambda的标准格式
(参数类型1 参数名1, 参数类型2 参数名2)->{...方法体的代码...return 返回值;}
标准格式的基础上()中的
参数类型
可以直接省略(参数名1, 参数名2)->{...方法体的代码...return 返回值;}
如果{}总的语句
只有一条语句
,则{}
可以省略、return关键字
、以及最后的“;”
都可以省略(参数名1, 参数名2)-> 结果
如果()里面
只有一个参数
,则()可以省略参数名->结果
体验:
匿名内部类写法
1.对数组中的每一个元素*0.8Arrays.setAll(prices, new IntToDoubleFunction() {@Overridepublic double applyAsDouble(int value) {// value = 0 1 2return prices[value] * 0.8;}}); ----------------------------------------------------------------- Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序} });
Lambda表达式标准写法
Arrays.setAll(prices, (int value) -> {return prices[value] * 0.8;}); ----------------------------------------------------------------- Arrays.sort(students, (Student o1, Student o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});
使用Lambda表达式简化格式1——
省略参数类型
Arrays.setAll(prices, (value) -> {return prices[value] * 0.8;}); ----------------------------------------------------------------- Arrays.sort(students, ( o1, o2) -> {return Double.compare(o1.getHeight(), o2.getHeight()); // 升序});
使用Lambda表达式简化格式2——
省略()
Arrays.setAll(prices, value -> {return prices[value] * 0.8;});
使用Lambda表达式简化格式3——
省略{}
Arrays.setAll(prices, value -> prices[value] * 0.8 ); ----------------------------------------------------------------- Arrays.sort(students, ( o1, o2) -> Double.compare(o1.getHeight(), o2.getHeight()));
方法引用
JDK8的另一个新特性,叫做方法引用。我们知道Lambda是用来简化匿名代码的书写格式的,而方法引用是用来进一步简化Lambda表达式的,它简化的更加过分。
静态方法引用
Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {return o1.getAge() - o2.getAge(); // 按照年龄升序排序}});
使用Lambda简化后:
Arrays.sort(students, (o1, o2) -> o1.getAge() - o2.getAge());
Lambda表达式的
方法体
,用一个静态方法代替
- 准备另外一个类
CompareByData
类,用于封装Lambda表达式的方法体
代码;public class CompareByData {public static int compareByAge(Student o1, Student o2){return o1.getAge() - o2.getAge(); // 升序排序的规则} }
因此可以改成如下代码:
Arrays.sort(students, (o1, o2) -> CompareByData.compareByAge(o1, o2));
**实际上就是用类名调用方法,但是把参数给省略了。**这就是
静态方法引用
//静态方法引用:类名::方法名 Arrays.sort(students, CompareByData::compareByAge);
实例方法引用
把下图中Lambda表达式的方法体,用一个实例方法代替。
我们把Lambda表达式的方法体,改用
对象调用
方法CompareByData compare = new CompareByData(); Arrays.sort(students, (o1, o2) -> compare.compareByAgeDesc(o1, o2)); // 降序
再将Lambda表达式的方法体,直接改成方法引用写法。实际上就是用类名调用方法,但是省略的参数。这就是实例方法引用
CompareByData compare = new CompareByData(); Arrays.sort(students, compare::compareByAgeDesc); // 降序
特定类型的方法引用
如果某个Lambda表达式里只是调用一个
实例方法
,并且前面参数列表中的第一个参数作为方法的主调
,后面的所有参数都是作为该实例方法的入参
时,则就可以使用特定类型的方法引用
。格式:类型::方法名
public class Test2 {public static void main(String[] args) {String[] names = {"boby", "angela", "Andy" ,"dlei", "caocao", "Babo", "jack", "Cici"};// 要求忽略首字符大小写进行排序。Arrays.sort(names, new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {// 制定比较规则。o1 = "Andy" o2 = "angela"return o1.compareToIgnoreCase(o2);}});//lambda表达式写法Arrays.sort(names, ( o1, o2) -> o1.compareToIgnoreCase(o2) );//特定类型的方法引用!Arrays.sort(names, String::compareToIgnoreCase);System.out.println(Arrays.toString(names));} }
构造器引用
开发中应用不多,仅做语法补充。
-
准备一个函数式接口,接口中代码的返回值类型是Car类型
-
interface CreateCar{Car create(String name, double price); }
具体简化步骤如下:
// 1、创建这个接口的匿名内部类对象。CreateCar cc1 = new CreateCar(){@Overridepublic Car create(String name, double price) {return new Car(name, price);}}; //2、使用匿名内部类改进CreateCar cc2 = (name, price) -> new Car(name, price);//3、使用方法引用改进:构造器引用CreateCar cc3 = Car::new;//注意:以上是创建CreateCar接口实现类对象的几种形式而已,语法一步一步简化。//4、对象调用方法Car car = cc3.create("奔驰", 49.9);System.out.println(car);