JDK8~13新特性概览
JDK8
1. 接口default 与 static 关键字
/** * jdk8中接口可以使用声明default和static修饰的方法 * static修饰的方法和普通的方法一样,可以被直接调用 * default修饰的方法有方法体,就和普通的方法一样,可以被重写,有点像抽象类的方法一样,但是java是单继承多实现的 */ public interface Today { void dream(); void striver(); default void victory(){ System.out.println("未来"); } static void test(){ System.out.println("接口里的静态方法"); } // jdk9 中还新增了private方法 private void test3() { System.out.println("私有方法"); }; }
2. base64 api
import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; import java.util.Base64; /** * Base64是⽹络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是 * 一种基于64个可打印字符来表示二进制数据的方法 基于64个字符A-Z,a-z,0-9,+,/的编码方式, * 是一种能将任意二进制数据用64种字元组合成字符串的方法, */ public class Main { public static void main(String[] args) throws Exception { /** * jdk8以前的写法 * 编码和解码的效率⽐较差,公开信息说以后的版本会取消这个⽅法 */ BASE64Encoder encoder = new BASE64Encoder(); BASE64Decoder decoder = new BASE64Decoder(); byte[] textByte = "圣魔导师".getBytes("UTF-8"); //编码 String encodedText = encoder.encode(textByte); System.out.println(encodedText);//5Zyj6a2U5a+85biI //解码 System.out.println(new String(decoder.decodeBuffer(encodedText),"UTF-8"));//圣魔导师 /** * jdk8的写法 * 编解码销量远⼤于 sun.misc 和 Apache Commons Codec,可以自己动手压测一下速度 */ Base64.Decoder decoder2 = Base64.getDecoder(); Base64.Encoder encoder2 = Base64.getEncoder(); byte[] textByte2 = "圣魔导师".getBytes("UTF-8"); //编码 String encodedText2 = encoder2.encodeToString(textByte2); System.out.println(encodedText);//5Zyj6a2U5a+85biI //解码 System.out.println(new String(decoder2.decode(encodedText2), "UTF-8"));//圣魔导师 } }
3. 简便的日期工具类
import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; /** * SimpleDateFormat,Calendar等类的 API设计⽐较差,⽇期/时间对象⽐较,加减麻烦,Date 还是⾮线程安全的; * 所以 Java 8通过发布新的 java.time里的工具类来简化处理,如⽇期/时间的⽐较,加减,格式化。 * 核⼼类: * LocalDate:不包含具体时间的⽇期。 * LocalTime:不含⽇期的时间。 * LocalDateTime:包含了⽇期及时间。 */ public class Main { public static void main(String[] args) throws Exception { Main main = new Main(); LocalTime localTime = LocalTime.now(); System.out.println("现在时间:"+localTime);// 现在时间:23:00:49.476 System.out.println("============= localTime常用方法 ============="); main.localTime(); System.out.println("============= localDateTime常用方法 ============="); main.localDateTime(); } public void localTime(){ LocalDate today = LocalDate.now(); System.out.println("今天⽇期:" + today);// 今天⽇期:2019-11-07 //获取年,⽉,⽇,周⼏ System.out.println("现在是哪年:"+today.getYear());// 现在是哪年:2019 System.out.println("现在是哪⽉(英文):"+today.getMonth());// 现在是哪⽉(英文):NOVEMBER System.out.println("现在是哪⽉(数字):"+today.getMonthValue());// 现在是哪⽉(数字):11 System.out.println("现在是⼏号:"+today.getDayOfMonth());// 现在是⼏号:7 System.out.println("现在是周⼏:"+today.getDayOfWeek());// 现在是周⼏:THURSDAY //加减年份, 加后返回的对象才是修改的,旧的依然是旧的 LocalDate changeDate = today.plusYears(1); System.out.println("加后是哪年:"+changeDate.getYear());// 加后是哪年:2020 System.out.println("旧的是哪年:"+today.getYear());// 旧的是哪年:2019 //日期比较 System.out.println("isAfter:"+changeDate.isAfter(today));// isAfter:true /* //getYear() int 获取当前⽇期的年份 //getMonth() Month 获取当前⽇期的⽉份对象 //getMonthValue() int 获取当前⽇期是第⼏⽉ //getDayOfWeek() DayOfWeek 表示该对象表示的⽇期是星期⼏ //getDayOfMonth() int 表示该对象表示的⽇期是这个⽉第⼏天 //getDayOfYear() int 表示该对象表示的⽇期是今年第⼏天 //withYear(int year) LocalDate 修改当前对象的年份 //withMonth(int month) LocalDate 修改当前对象的⽉份 //withDayOfMonth(int dayOfMonth) LocalDate 修改当前对象在当⽉的⽇期 //plusYears(long yearsToAdd) LocalDate 当前对象增加指定的年份数 //plusMonths(long monthsToAdd) LocalDate 当前对象增加指定的⽉份数 //plusWeeks(long weeksToAdd) LocalDate 当前对象增加指定的周数 //plusDays(long daysToAdd) LocalDate 当前对象增加指定的天数 //minusYears(long yearsToSubtract) LocalDate 当前对象减去指定的年数 //minusMonths(long monthsToSubtract) LocalDate 当前对象减去注定的⽉数 //minusWeeks(long weeksToSubtract) LocalDate 当前对象减去指定的周数 //minusDays(long daysToSubtract) LocalDate 当前对象减去指定的天数 //compareTo(ChronoLocalDate other) int ⽐较当前对象和other对象在时间上的⼤⼩,返回值如果为正,则当前对象时间较晚, //isBefore(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否在other对象⽇期之前 //isAfter(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否在other对象⽇期之后 //isEqual(ChronoLocalDate other) boolean ⽐较两个⽇期对象是否相等 */ } public void localDateTime(){ // DateTimeFormatter是线程安全的SimpleDateFormat LocalDateTime ldt = LocalDateTime.now(); System.out.println(ldt);// 2019-11-07T23:12:29.056 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String ldtStr = dtf.format(ldt); System.out.println(ldtStr);// 2019-11-07 23:12:29 // 获取指定的⽇期时间对象 LocalDateTime ldt2 = LocalDateTime.of(2020, 11, 11, 8, 20, 30); System.out.println(ldt2);// 2020-11-11T08:20:30 // 计算⽇期时间差 java.time.Duration LocalDateTime today = LocalDateTime.now(); System.out.println(today);// 2019-11-07T23:12:29.070 LocalDateTime changeDate = LocalDateTime.of(2020,10,1,10,40,30); System.out.println(changeDate);// 2020-10-01T10:40:30 Duration duration = Duration.between( today,changeDate);//第⼆个参数减第⼀个参数 System.out.println(duration.toDays());//两个时间差的天数 System.out.println(duration.toHours());//两个时间差的⼩时数 System.out.println(duration.toMinutes());//两个时间差的分钟数 System.out.println(duration.toMillis());//两个时间差的毫秒数 System.out.println(duration.toNanos());//两个时间差的纳秒数 } }
4. lambda 与 函数式编程
import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * 面向对象编程是对数据的抽象(各种各样的POJO类); * 函数式编程则是对行为的抽象(将行为作为一个参数进行传递) * 所谓的函数编程,即可理解是将一个函数(也称为“行为”)作为⼀个参数进行传递 * * lambda表达式 使⽤场景:接口中只能有一个方法, * 比如Runnable接口里的run方法;Comparator接口里的compareTo方法 * Lambda 表达式的实现方式在本质是以匿名内部类的方式进行实现的 */ public class Main { public static void main(String[] args) throws Exception { new Thread(new Runnable() { @Override public void run() { System.out.println("jdk8以前创建线程"); } }); //()对应run()没有一个参数,->后面是方法体内容 //如果{}中的代码只有⼀行,⽆论有返回值,可以省略{}、return、分号,其他则需要加上 new Thread(()-> System.out.println("lambda表达式创建线程")); List<String> list = Arrays.asList("a","c","d","b","e"); // jdk8以前排序 Collections.sort(list, new Comparator<String>() { @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }); // lambda表达式排序 //,前面的对应接口前面的参数,a b 对应compare里面的参数 Collections.sort(list,(a,b)->b.compareTo(a)); } } ================== 自定义函数是编程(1) ==================== /** * 像Runnable接口一样用FunctionalInterface注解修饰 * 加了这个注解后,接口里面必须有且只能有一个方法 */ @FunctionalInterface public interface Test1<R,T>{ // R表示返回值,T表示参数类型,t1 t2是具体参数 R operator(T t1, T t2); } public class Compute { /** * 定义一个函数方法 * 需要传入a和b两个参数, * 后面的Test1<Integer,Integer> of就是传入的一个函数(行为),of是随便起的一个别名 */ public static Integer operator(Integer a,Integer b,Test1<Integer,Integer> of){ return of.operator(a,b); } } public class Main { public static void main(String[] args) throws Exception { System.out.println(Compute.operator(2,3,(a,b)-> a+b)); System.out.println(Compute.operator(2,3,(a,b)-> a-b)); System.out.println(Compute.operator(2,3,(a,b)-> a*b)); System.out.println(Compute.operator(2,3,(a,b)-> a/b)); } } ================== 自定义函数是编程(2) ==================== @FunctionalInterface public interface Test2{ void test(); } public class Main { public static void main(String[] args) throws Exception { Main.casesc(()-> System.out.println("函数式编程案例二")); } public static void casesc(Test2 t){ t.test(); } }
5. 四大核心函数式接口
Lambda表达式必须先定义接口,创建相关方法之后才能调用,这样做十分不便,其实java8已经内置了许多接口, 例如下面四个功能型接口.所有标注@FunctionalInterface注解的接口都是函数式接口
public class Main { public static void main(String[] args) throws Exception { Consumer<String> c1 = obj->System.out.println(obj+": 调⽤用短信接⼝口发送短信,或者打印⽇日志"); c1.accept("订单id—001"); Consumer<List> c2 = obj->{ if(obj==null || obj.size()<1)return; obj.forEach(o-> System.out.println(o)); }; List<Integer> list = Arrays.asList(2,4,0,8,9,7); c2.accept(list); } }
public class Main { public static void main(String[] args) throws Exception { Student student = newStudent(); System.out.println(student); } public static Student newStudent(){ Supplier<Student> supplier = ()-> { Student student = new Student(); student.setName("默认名称"); return student; }; return supplier.get(); } } class Student{ private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + '}'; } }
Function:只能接受一个参数 用法一(用一个类实现接口里面的逻辑,然后直接调用) public class FunctionObj implements Function { @Override public Object apply(Object o) { return "对参数:"+o+"经过处理后返回结果"; } } public class Main { public static void main(String[] args) throws Exception { System.out.println(test("hello",new FunctionObj())); } public static String test(String a ,FunctionObj functionObj){ return functionObj.apply(a).toString(); } } 用法二(左边规定好参数和返回值类型,右边写方法体具体逻辑) public class Main { public static void main(String[] args) throws Exception { Function<Integer,Integer> func = p->{ return p*100; }; System.out.println(func.apply(12)); Function<Integer,Boolean> function = a->a<100; System.out.println(function.apply(97)); } } ================================================================= BiFunctionObj:能接受两个参数 // 用法一 public class BiFunctionObj implements BiFunction { @Override public Object apply(Object o, Object o2) { return (Integer.valueOf(o.toString())+Integer.valueOf(o2.toString())); } } public class Main { public static void main(String[] args) throws Exception { System.out.println(test(2,5,new BiFunctionObj())); } public static Integer test(Integer a,Integer b, BiFunctionObj func){ return Integer.valueOf(func.apply(a,b).toString()); } } // 用法二 public class Main { public static void main(String[] args) throws Exception { BiFunction<Integer, Integer,Boolean> func1 = (a,b)->{ return a>b; }; System.out.println(func1.apply(1,5)); BiFunction<String, String,String> func2 = (a,b)->a+b; System.out.println(func2.apply("hellow","world")); } }
public class Main { public static void main(String[] args) throws Exception { Predicate<Integer> predicate = a->a>10; List<Integer> list = Arrays.asList(1,54,9,34,3); for(Integer l : list){ if(predicate.test(l)) System.out.println(l); } } }
6. 流操作
/** * Stream:通过将集合转换为这么⼀种叫做 “流”的元素队列,能够对集合中的每个元素进行任意操作。总共分为4个步骤: * 数据元素便是原始集合:如List、Set、Map等 * 生成流:可以是串行流stream() 或者并行流 parallelStream() * 中间操作:可以是 排序,聚合,过滤,转换等 * 终端操作:统一收集返回一个流 * * 一般都采用stream,因为集合操作一般里面就几百条数据,多线程的并行流效率不一定就高,还会出现线程安全问题 */ public class Main { public static void main(String[] args) { List<String> list = Arrays.asList("张麻子","李蛋","王二狗","Angell"); List<Student> users = Arrays.asList(new Student("张三", 23), new Student("赵四", 24), new Student("二狗", 23), new Student("田七", 22), new Student("皮特", 20), new Student("Tony", 20), new Student("二柱子", 25)); /** * map:对集合的每个对象做处理 */ List<String> collect = list.stream().map(obj->"哈哈"+obj).collect(Collectors.toList()); list.forEach(obj->System.out.println(obj)); System.out.println("----------------"); collect.forEach(obj->System.out.println(obj)); /** * filter:boolean判断,用于条件过滤 */ System.out.println("----------------"); Set<String> set = list.stream().filter(obj->obj.length()>2).collect(Collectors.toSet()); set.forEach(obj->System.out.println(obj)); /** * sorted:对流进行自然排序 */ System.out.println("----------------"); Set<String> sorteds = list.stream().sorted().collect(Collectors.toSet()); sorteds.forEach(obj->System.out.println(obj)); // 自定义排序规则 // 根据长度排序(正序) System.out.println("----------------"); List<String> resultList = list.stream().sorted(Comparator.comparing(obj -> obj.length())).collect(Collectors.toList()); resultList.forEach(obj->System.out.println(obj)); System.out.println("----------------"); // 根据长度排序(倒序) List<String> resultList2 = list.stream().sorted(Comparator.comparing(obj -> obj.length(),Comparator.reverseOrder())).collect(Collectors.toList()); resultList2.forEach(obj->System.out.println(obj)); System.out.println("----------------"); // 手动指定排序规则(根据年龄大小排序) List<Student> collect2 = users.stream().sorted( Comparator.comparing(Student::getAge,(x,y)->{ if(x>y) { return 1; }else { return -1; } }) ).collect(Collectors.toList()); collect2.forEach(obj->System.out.println(obj.getAge()+" : "+obj.getProvince())); /** * limit:截取包含指定数量的元素 */ System.out.println("----------------"); List<String> collect3 = list.stream().limit(2).collect(Collectors.toList()); collect3.forEach(obj->System.out.println(obj)); /** * allMatch:匹配所有元素,只有全部符合才返回true */ System.out.println("----------------"); boolean flag = list.stream().allMatch(obj->obj.length()>2); System.out.println(flag); System.out.println("----------------"); /** * anyMatch:匹配所有元素,至少一个元素满足就为true */ boolean flag2 = list.stream().anyMatch(obj->obj.length()>2); System.out.println(flag2); System.out.println("----------------"); /** * max和min:最大值和最小值 */ Optional<Student> max = users.stream().max(Comparator.comparingInt(Student::getAge)); System.out.println(max.get().getAge()+" : "+max.get().getProvince()); System.out.println("----------------"); Optional<Student> min = users.stream().min((s1, s2)->Integer.compare(s1.getAge(),s2.getAge())); System.out.println(min.get().getAge()+" : "+min.get().getProvince()); /** * reduce:对Stream中的元素进行计算后返回一个唯一的值 */ // 计算所有值的累加 int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1 + item2).get(); // 100作为初始值,然后累加所有值 int value2 =Stream.of(1, 2, 3, 4, 5).reduce(100, (sum, item) -> sum + item); // 找出最大值 int value3 =Stream.of(1, 4, 5, 2, 3).reduce((x,y)->x>y?x:y).get(); System.out.println(value); System.out.println(value2); System.out.println(value3); } } class Student { private String province; private int age; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String province, int age) { this.age = age; this.province = province; } }
7. 终端操作收集器:Collector
/** * 数据结构收集:Collectors */ public class Main { public static void main(String[] args) throws Exception { List<String> data = Arrays.asList("张三","王五","李四"); List<String> list = data.stream().collect(Collectors.toList()); Set<String> set = data.stream().collect(Collectors.toSet()); LinkedList<String> linkedList = data.stream().collect(Collectors.toCollection(LinkedList::new)); System.out.println(list); System.out.println(set); System.out.println(linkedList); /* Collectors.toMap() Collectors.toSet() Collectors.toCollection() :⽤用⾃自定义的实现Collection的数据结构收集 Collectors.toCollection(LinkedList::new) Collectors.toCollection(CopyOnWriteArrayList::new) Collectors.toCollection(TreeSet::new) */ } } //============================================================ /** * 拼接函数:joining */ public class Main { public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("springBoot","springCloud","netty"); String result1 = list.stream().collect(Collectors.joining()); String result2 = list.stream().collect(Collectors.joining("——")); String result3 = list.stream().collect(Collectors.joining("—", "【","")); String result4 = Stream.of("hello", "world").collect(Collectors.joining("—", "【", "】")); System.out.println(result1); System.out.println(result2); System.out.println(result3); System.out.println(result4); } } //============================================================ /** * 分组:partitioningBy */ public class Main { public static void main(String[] args) throws Exception { List<String> list = Arrays.asList("sdfsdf","xxxx","bbb","bbb"); Map<Boolean, List<String>> collect = list.stream().collect(Collectors.partitioningBy(obj -> obj.length() > 3)); System.out.println(collect); } } //============================================================ /** * 分组:group by * 统计:counting */ public class Main { public static void main(String[] args) throws Exception { List<Student> students = Arrays.asList( new Student("⼴东", 23), new Student("⼴东", 24), new Student("⼴东", 23), new Student("北京", 22), new Student("北京", 20), new Student("北京", 20), new Student("海南", 25)); // 通过名称分组 Map<String, List<Student>> listMap = students.stream().collect(Collectors.groupingBy(obj -> obj.getProvince())); listMap.forEach((key, value) -> { System.out.println("========"); System.out.println(key); value.forEach(obj -> { System.out.println(obj.getAge()); }); }); System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); // 根据名称分组,并统计每个分组的个数 Map<String, Long> map = students.stream().collect(Collectors.groupingBy(Student::getProvince, Collectors.counting())); map.forEach((key,value)->{ System.out.println(key+"省人数有"+value); }); } } class Student { private String province; private int age; public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Student(String province, int age) { this.age = age; this.province = province; } } //============================================================ /** * 统计函数:summarizing */ public class Main { public static void main(String[] args) throws Exception { List<Student> students = Arrays.asList( new Student("⼴东", 23), new Student("⼴东", 24), new Student("⼴东", 23), new Student("北京", 22), new Student("北京", 20), new Student("北京", 20), new Student("海南", 25)); // summarizingInt; summarizingLong; summarizingDouble IntSummaryStatistics summaryStatistics = students.stream().collect(Collectors.summarizingInt(Student::getAge)); System.out.println("平均值:" + summaryStatistics.getAverage()); System.out.println("人数:" + summaryStatistics.getCount()); System.out.println("最大值:" + summaryStatistics.getMax()); System.out.println("最小值:" + summaryStatistics.getMin()); System.out.println("总和:" + summaryStatistics.getSum()); } } /** * reduce:对Stream中的元素进行计算后返回一个唯一的值 */ // 计算所有值的累加 int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1 + item2).get(); // 100作为初始值,然后累加所有值 int value2 =Stream.of(1, 2, 3, 4, 5).reduce(100, (sum, item) -> sum + item); // 找出最大值 int value3 =Stream.of(1, 4, 5, 2, 3).reduce((x,y)->x>y?x:y).get(); System.out.println(value); System.out.println(value2); System.out.println(value3);
JDK9
1. try-with-resource
import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class Main { public static void main(String[] args) throws Exception { String path = "/Users/jack/Desktop/t.txt"; /** * jdk 1.7以前关闭资源一般是在finally里面操作的 */ OutputStream out = new FileOutputStream(path); try { out.write(("一壶漂泊,浪迹天涯难入喉;你走之后,酒暖回忆思念瘦").getBytes()); } catch (Exception e) { e.printStackTrace(); }finally { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } /** * jdk1.7的时候,可以在try()里声明资源,会在try-catch代码块结束后自动关闭掉。 * try结束后自动调用的close方法,这个动作会早于finally里调用的方法 * bu管是否出现异常,try()里的实例都会被调用close方法 * try里面可以声明多个自动关闭的对象,越早声明的对象,会越晚被close掉 */ try (OutputStream out2 = new FileOutputStream(path);){ out2.write(("一壶漂泊,浪迹天涯难入喉;你走之后,酒暖回忆思念瘦").getBytes()); } catch (Exception e) { e.printStackTrace(); } /** * jdk1.9之后,对try()做了改进,在try外进行初始化,在括号内引用 */ OutputStream out3 = new FileOutputStream(path); try (out3) { out3.write(("一壶漂泊,浪迹天涯难入喉;你走之后,酒暖回忆思念瘦").getBytes()); } catch (Exception e) { e.printStackTrace(); } } }
2. stream
public class Main { /** * jdk9中的Stream流新增了两个api */ public static void main(String[] args) throws Exception { /** * takeWhile:遍历每个对象,直到遇到第⼀个false时,返回前面所有元素,如果没有false,将返回⼀一个空的 Stream */ List<String> list1 = List.of("springboot","java","html","","git").stream() .takeWhile(obj->!obj.isEmpty()).collect(Collectors.toList()); System.out.println(list1); /** * dropWhile:与takeWhile相反 */ List<String> list2 = List.of("springboot","java","html","","git").stream() .dropWhile(obj->!obj.isEmpty()).collect(Collectors.toList()); System.out.println(list2); } }
3. of创建只读集合
public class Main { public static void main(String[] args) throws Exception { /** * JDK9之前创建只读集合 */ List<String> list = new ArrayList<String>(); list.add("张三"); list.add("李四"); list.add("王五"); list.remove(0); System.out.println(list); //设置为只读List集合 // unmodifiableMap(map); unmodifiableMap(set); list = Collections.unmodifiableList(list); // 报错:java.lang.UnsupportedOperationException //list.remove(0); System.out.println(list); /** * jdk9创建只读集合 */ List<String> list2 = List.of("mysql", "linux", "redis"); list2.remove(0); System.out.println(list2); } }
JDK10
1. var作为局部变量类型推断标识符
public class Main { // var作为局部变量类型推断标识符 public static void main(String[] args) throws Exception { var strVar = "springboot"; System.out.println(strVar instanceof String); //根据10L 推断long 类型 var longVar = Long.valueOf(10l); System.out.println(longVar instanceof Long); //根据 true推断 boolean 类型 var flag = Boolean.valueOf("true"); System.out.println(flag instanceof Boolean); // 推断 ArrayList<String> var listVar = new ArrayList<String>(); System.out.println(listVar instanceof ArrayList); // 推断 Stream<String> var streamVar = Stream.of("aa", "bb", "cc"); System.out.println(streamVar instanceof Stream); if(flag){ System.out.println("这个是 flag 变量,值为true"); } for (var i = 0; i < 10; i++) { System.out.println(i); } try (var input = new FileInputStream("validation.txt")) { } } }
JDK11
1. httpclinet
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; import java.util.concurrent.CompletableFuture; /** * 这个功能在JDK9中引入,在JDK10中得到了更新,在JDK11才发布 */ public class Main { private static final URI uri = URI.create("https://www.cnblogs.com/wlwl/"); public static void main(String[] args) { testHttp2(); } /** * get请求 */ private static void testGet() { // 创建连接两种方式: var httpClient = HttpClient.newHttpClient(); var httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(5000)).build(); // 封装请求参数(默认get请求) HttpRequest request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000)) .header("key1", "v1") .uri(uri).build(); try { var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } /** * post请求 */ private static void testPost() { HttpClient httpClient = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder().uri(uri) .POST(HttpRequest.BodyPublishers.ofString("phone=13113777337&pwd=1234567890")) // from表单要用下面格式发送 //.header("Content-Type", "application/json") //.POST(HttpRequest.BodyPublishers.ofString("{\"phone\":\"13113777337\",\"pwd\":\"1234567890\"}")) .build(); try { var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (Exception e) { e.printStackTrace(); } } /** * 异步GET请求 */ private static void testAsynGet() { var httpClient = HttpClient.newBuilder().build(); var request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000)) .header("key1", "v1") .uri(uri).build(); try { // 异步请求通过CompletableFuture实现 CompletableFuture<String> result = httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body); System.out.println(result.get()); } catch (Exception e) { e.printStackTrace(); } } /** * 发送http2请求 * HTTP2协议的强制要求https,如果目标URI是HTTP的,则无法使用HTTP 2协议 */ private static void testHttp2() { var httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(3000)) .version(HttpClient.Version.HTTP_2) .build(); var request = HttpRequest.newBuilder().timeout(Duration.ofMillis(3000)) .header("key1", "v1") .uri(uri) .build(); try { var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); System.out.println(response.version()); } catch (Exception e) { e.printStackTrace(); } } }
JDK13
1. switch
public class Main { public static void main(String[] args) { testOldSwitch1(); } /** * 旧:没有break,则匹配的case后⾯面会⼀一直输出 */ public static void testOldSwitch1(){ int i = 1; switch(i){ case 0: System.out.println("zero"); //break; case 1: System.out.println("one"); //break; case 2: System.out.println("two"); //break; default: System.out.println("default"); } } /** * 新:使用箭头函数,不用声明break,会自动终止,支持多个值匹配,使用逗号分隔 */ public void testNewSwitch(int i){ switch(i){ case 0 -> { System.out.println("zero"); System.out.println("这是多⾏行行语句句"); } case 1,11,111 -> System.out.println("one"); case 2 -> System.out.println("two"); default -> System.out.println("default"); } } }
2. 多行文本块
public class Main { public static void main(String[] args) { /** * 旧:在java代码里面编写多行源码带有特殊字符则需要转义,如HTML,sql等 */ String html = "<html>\n" + "<body>\n" + "<p>Hello, world</p>\n" + "</body>\n" + "</html>\n"; String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\n" + "WHERE `CITY` = 'INDIANAPOLIS'\n" + "ORDER BY `EMP_ID`, `LAST_NAME`;\n"; /** * 新:不用对转义字符进行转义 */ String html2 = """" <html> <body> <p>Hello, world</p> </body> </html> """; String query = """ SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` WHERE `CITY` = 'INDIANAPOLIS' ORDER BY `EMP_ID`, `LAST_NAME`; """; } }