学习jdk8-13新特性笔记

jdk8的新特性

  1. 接口增强,default,static关键字
    在jdk1.8只前接口中只能使用抽象方法,而不能有任何方法的实现的
    jdk1.8里面则可以声明default和static修饰的方法
/**
 * @Date: 2019/11/16 11:10
 * @Description:
 * 在jdk1.8以前接⼝⾥⾯是只能有抽象⽅法,不能有任何⽅法的实现的
 * 但是jdk1.8⾥⾯打破了这个规定,引⼊了新的关键字default,使⽤default修饰⽅法,可以在接⼝⾥⾯定义具体的⽅法实现
 * default修饰的方法称为默认⽅法,这个接⼝的实现类实现了这个接⼝之后,可以被重写,类似像抽象类的方法一样
 * static修饰的方法和普通的方法一样,可以被直接调用
 * jdk 9新增private方法
 */
public interface student {

    void study();

    default void testMethod(){
        System.out.println("接口里的默认方法");
    }

    static void staticMethod(){
        System.out.println("接口里的静态方法");
    }

    // jdk9 新增private方法
    private void privateMethod() {
        System.out.println("jdk9  新增私有方法");
    };
}
  1. 日期处理类
  • SimpleDateFormate,Calendar旧版的缺点: java.util.Date 是非线程安全的api,涉及的比较差,日期时间的计算,比较都相对的麻烦
  • java 8新增日期处理类:LocalDate、LocalTime、Instant、Duration以及Period,这些类都包含在java.time包中
/**
 * @Date: 2019/11/16 11:12
 * @Description: LocalDate LocalTime LocalDateTime api类似
 */
public class DateTest {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now();
        System.out.println(today);
        //获取年月日
        System.out.println(today.getYear());
        System.out.println(today.getMonth());
        System.out.println(today.getDayOfMonth());
        System.out.println(today.getDayOfWeek());
        //加减年份,加厚返回的对象才是修改后的,旧的依旧是旧的
        LocalDate changeDate = today.plusYears(1);
        System.out.println(changeDate.getYear());
        System.out.println(today.getYear());
        //日期比较
        //是否在之前
        System.out.println("isbefore:"+today.isBefore(changeDate));
        //是否在之后
        System.out.println("isbefore:"+today.isAfter(changeDate));

   		// jdk8引入 DateTimeFormatter是线程安全的SimpleDateFormat
        LocalDateTime lt = LocalDateTime.now();
        System.out.println(lt);// 2019-11-07T23:12:29.056
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String ldtStr = dtf.format(lt);
        System.out.println(ldtStr);// 2019-11-07 23:12:29
        
        //获取指定时间对象
        LocalDateTime ldt = LocalDateTime.of(2020,10,1,10,40,30);
        System.out.println(changeDate);// 2020-10-01T10:40:30

        //Duration基于时间值,Period基于日期值,
        //Duration类表示秒或纳秒时间间隔
        //适合处理较短的时间,需要更高的精确性。使用between()方法比较两个瞬间的差:
        Instant start = Instant.parse("2019-11-16T11:15:30.00Z");
        Instant end = Instant.parse("2019-11-16T11:16:30.00Z");
        Duration duration = Duration.between(start,end);//第⼆个参数减第⼀个参数
        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());//两个时间差的纳秒数

        //Period 类表示一段时间的年、月、日,使用between()方法获取两个日期之间的差
        LocalDate startDate = LocalDate.of(2019, 11, 16);
        LocalDate endDate = LocalDate.of(2020, 1, 1);
        Period period = Period.between(startDate,endDate);
        System.out.println("per:"+period.getYears());//两个时间差的年数
        System.out.println("per:"+period.getMonths());//两个时间差的月
    }
}
  1. base64
    新增base64 编解码api
    public static void main(String args[]) throws UnsupportedEncodingException {
      Base64.Encoder encoder = Base64.getEncoder();
      Base64.Decoder decoder = Base64.getDecoder();

      String str = "这是一个测试";
      byte[] bytes = str.getBytes("utf-8");

      String encodText = encoder.encodeToString(bytes);
      System.out.println(encodText);

      System.out.println(new String(decoder.decode(encodText),"utf-8"));

  }
  1. Optionnal类

Optional类的作用:
- 主要解决的问题是:空指针异常 NullPointerException
- 本质上是一个包含有可选值的包装类,Opertional类既可以为含有对象也可以为空

1> 创建opertional类
of()
null传进去会报错

	Optional<Student> opt = Optional.of(user);

ofNullable()
对象可能是null也可能是非null 就应该使用ofNullable()

	Optional<Student> opt = Optional.ofNullable(user);

2>访问Optional对象的值
get()

	Optional<Student> opt = Optional.ofNullable(student); 
	Student s = opt.get();

如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象一般使用get之前需要先验证是否有值,不然会报错

	public static void main(String[] args) {
	 Student student = null;
	 test(student);
	}
	public static void test(Student student){
	 Optional<Student> opt = Optional.ofNullable(student);
	 System.out.println(opt.isPresent());
	}

3>兜底方法
使用:当value值为null时,给予一个默认值:
方法1:orElse(T other)
方法2:orElseGet(Supplier other)
方法3:orElseThrow(Supplier exceptionSupplier)

	@Test
	public void test() {
	    Student student= null;
	    Student= Optional.ofNullable(student).orElse(createStudent());
	    Student= Optional.ofNullable(student).orElseGet(() -> createStudent());
		Student= Optional.ofNullable(student).orElseThrow(()->new Exception("学生不存在"));
	
	}
	public User createStudent(){
	    Studentstudent = new Student();
	    student.setName("stu");
	    return user;
	}

orElse和orElseGet二者区别
orElse()方法在Optional值为非空时,也会计算传入的参数,而orElseGet()方法只有在Optional值为空时才会执行传入的函数。
由于orElseGet()不是每次都会调用传入的方法,所以orElseGet()方法在性能上要优于orElse()方法。一般情况下,个人推荐使用orElseGet()方法更好

4>map()和faltMap()
map(Function mapper)
如果有值,则对其执行调用mapping函数得到返回值。如果返回值不为null,则创建包含mapping返回值的Optional作为map方法返回值,否则返回空Optional。


	Optional<String> upperName = name.map((value) -> value.toUpperCase());
	System.out.println(upperName.orElse("name is null"));

这两个函数,在函数体上没什么区别。唯一区别的就是入参,map函数所接受的入参类型为Function,而flapMap的入参类型为Function>

5> filter(Predicate predicate)
使用:如果有值并且满足断言条件返回包含该值的Optional,否则返回空Optional。

	Optional<Student> student= Optional.ofNullable(student).filter(s -> s.getName().length()<6);
  1. Lambda表达式

lambda表达式 使⽤场景(前提):⼀个接⼝中只包含⼀个⽅法,则可以使⽤Lambda表达式,这样
的接⼝称之为“函数接⼝” 语法: (params) -> expression

第⼀部分为括号内⽤逗号分隔的形式参数,参数是函数式接⼝⾥⾯⽅法的参数;第⼆部分为⼀个箭
头符号:->;第三部分为⽅法体,可以是表达式和代码块
参数列表 :
括号中参数列表的数据类型可以省略不写
括号中的参数只有⼀个,那么参数类型和()都可以省略不写
⽅法体:
如果{}中的代码只有⼀⾏,⽆论有返回值,可以省略{},return,分号,要⼀起省略,其他
则需要加上

1>Lambda 表达式的实现⽅式在本质是以匿名内部类的⽅式进⾏实现

public class lambdatest {
    public static void main(String[] args) {
        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));
    }
    
}

2>自定义lambda接口流程
定义⼀个函数式接⼝ 需要标注此接⼝ @FunctionalInterface,接口里面必须有且只能有一个方法

	@FunctionalInterface
	public interface OperFunction<R,T> {
	 // R表示返回值,T表示参数类型,t1 t2是具体参数
	 R operator(T t1, T t2);
	}
	
	public class cacl {

	    // 步骤:1定义一个函数方法 2 需要传入a和b两个参数 3传入的函数
	    public static Integer operator(Integer a,Integer b,Test1<Integer,Integer> of){
	        return of.operator(a,b);
	    }
	}

	public static void main(String[] args) throws Exception {
		System.out.println(cacl.operator(1,3,(a,b)-> a+b));
        System.out.println(cacl.operator(1,3,(a,b)-> a-b));
        System.out.println(cacl.operator(1,3,(a,b)-> a*b));
        System.out.println(cacl.operator(1,3,(a,b)-> a/b));
	 }

3>⽅法引⽤与构造函数引⽤
jdk1.8提供了另外⼀种调⽤⽅式 ::

说明:
⽅法引⽤是⼀种更简洁易懂的lambda表达式,操作符是双冒号::,⽤来直接访问类或者实例已经存在的⽅法或构造⽅法
通过⽅法引⽤,可以将⽅法的引⽤赋值给⼀个变量

语法:
	左边是容器(可以是类名,实例名),中间是" :: ",右边是相应的⽅法名
	静态⽅法,则是ClassName::methodName。如 Object ::equals
实例⽅法,则是Instance::methodName
构造函数,则是 类名::new;

单个参数
	Function<⼊参1, 返回类型> func = ⽅法引⽤
	应⽤ func.apply(⼊参);

两个参数
	BiFunction<⼊参1,⼊参2, 返回类型> func = ⽅法引⽤
	应⽤ func.apply(⼊参1,⼊参2);
  1. 函数式编程

内置的四⼤核⼼函数式接⼝

	Function<T, R> : 函数型接⼝:有⼊参,有返回值
	 R apply(T t);
	 
	Consumer<T> : 消费型接⼝:有⼊参,⽆返回值
	 void accept(T t);
	 
	Supplier<T> : 供给型接⼝:⽆⼊参,有返回值
	 T get();
	 
	Predicate<T> : 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean
	 boolean test(T t);

1> Function

  • 传⼊⼀个值经过函数的计算返回另⼀个值
  • T:⼊参类型,R:出参类型
    调⽤⽅法:R apply(T t)
  • 作⽤:将转换逻辑提取出来,解耦合
//function源码
	@FunctionalInterface
	public interface Function<T, R> {
	 R apply(T t);
	}
//BiFunction源码
	@FunctionalInterface
	public interface BiFunction<T, U, R> {
	 R apply(T t, U u);
	}
   public static void main(String[] args) throws Exception {
    	//一个参数一个返回值
        Function<Integer,Integer> func = a->{
            return a+1;
        };
        System.out.println(func.apply(1));
		//两个参数 一个返回值
		BiFunction<Integer, Integer,Boolean> func1 = (a,b)->{
           return a+b;
       	};			
}

2> Consumer< T >

  • Consumer 消费型接⼝:有⼊参,⽆返回值
  • 将 T 作为输⼊,不返回任何内容
    调⽤⽅法:void accept(T t);
  • 没有出参,一般用于打印(foreach() ),发送短信等消费动作
	@FunctionalInterface
	public interface Consumer<T> {
		void accept(T t);
	}
    public static void main(String[] args) throws Exception {
       //foreach遍历操作
       List<String> list = Arrays.asList("aaa","bbb");
	   list.forEach(obj->{
	   System.out.println(obj);
	   });
	   
	   Consumer<String> consumer = obj->{
		 System.out.println(obj);
		 System.out.println("调用consumer接口");
		};
	  sendMsg("8888888",consumer);
	  
	  }
	public static void sendMsg(String phone,Consumer<String> consumer){
	 consumer.accept(phone);
	 }
	   

3> Supplier : 供给型接⼝:⽆⼊参,有返回值

  • Supplier: 供给型接⼝:⽆⼊参,有返回值
  • T:出参类型;没有⼊参
  • 调⽤⽅法:T get()
  • 泛型⼀定和⽅法的返回值类型是⼀种类型,如果需要获得⼀个数据,并且不需要传⼊参数,可
    以使⽤Supplier接⼝,例如 ⽆参的⼯⼚⽅法,即⼯⼚设计模式创建对象,简单来说就是 提供者
	@FunctionalInterface
	public interface Supplier<T> {
	  T get();
	}
	public static void main(String[] args) {
	 	Student student = newStudent();
	 	System.out.println(student.getName());
	 }
	 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;
	 }
	 }

4> Predicate : 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean

  • Predicate: 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean
  • T:⼊参类型;出参类型是Boolean
  • 调⽤⽅法:boolean test(T t);
  • ⽤途: 接收⼀个参数,⽤于判断是否满⾜⼀定的条件,过滤数据
@FunctionalInterface
	public interface Predicate<T> {
		boolean test(T t);
	}
public static void main(String[] args) {
	 List<String> list =Arrays.asList("awewrwe","vdssdsd","aoooo","psdddsd");
	 List<String> results = filter(list,obj->obj.startsWith("a"));
	 System.out.println(results);
 }
 public static List<String> filter(List<String> list,Predicate<String> predicate) {
	 List<String> results = new ArrayList<>();
	 for (String str : list) {
	 	if (predicate.test(str)) {
	 		results.add(str);
	 	}
	 }
	 return results;
 }
  1. stream
  • 通过将集合转为一种stream流的元素队列,通过声明性⽅式,
    能够对集合中的每个元素进⾏⼀系列并⾏或串⾏的流⽔线操作
  • 元素是特定类型的对象,所以元素集合看作⼀种流, 流在管道中传输, 且可以在管道的节点上进⾏处理, ⽐如 排序,聚合,过滤等操作
  • stream的操作可以分为两类,中间操作和结束操作
数据集合
生成流
中间操作
终端操作

数据操作:

  • 数据元素便是原始集合,如List、Set、Map等
  • ⽣成流,可以是串⾏流stream() 或者并⾏流 parallelStream()
  • 中间操作,可以是 排序,聚合,过滤,转换等
  • 终端操作,很多流操作本身就会返回⼀个流,所以多个操作可以直接连接起来,最后统⼀进
    ⾏收集
 public static void main(String[] args) {
	List<User> list = Arrays.asList(
                // name,age
                new User("张三", 11),
                new User("王五", 20),
                new User("王五", 91),
                new User("张三", 8),
                new User("李四", 44),
                new User("李四", 44),
                new User("李四", 44)
        );
    //foreach 迭代
    list.forEach(user -> System.out.println(user));
    System.out.println("stream:");
    list.stream().forEach(user -> System.out.println(user));
  
    //将流中的每⼀个元素 T 映射为 R(类似类型转换
    List<String> mapUser= list.stream().map(obj->"用户:"+obj).collect(Collectors.toList());
    list.forEach(obj->System.out.println(obj));
    mapUser.forEach(obj->System.out.println(obj));
        
      //filter  使用该方法过滤 (Predicate)
	list.stream().filter(user -> user.getAge()>50).forEach(user -> System.out.println(user));

    //limit() 使用该方法截断
    list.stream().limit(3).forEach(user -> System.out.println(user));

     //skip() 与limit互斥,使用该方法跳过元素
    list.stream().skip(3).forEach(user-> System.out.println(user));

	//sort 排序
    List<User> users = list.stream().sorted(Comparator.comparing(User::getAge).reversed()).collect(Collectors.toList());
    System.out.println(users);
   
   //allmatch函数 检查是否匹配所有元素,只有全部符合才返回true
   List<String> list = Arrays.asList("springboot", "springcloud","redis","git", "netty", "java", "html", "docker");
   boolean flag = list.stream().allMatch(obj->obj.length()>1);
   System.out.println(flag);

	//anyMatch函数 检查是否⾄少匹配⼀个元素
	List<String> list = Arrays.asList("springboot", "springcloud","redis","git", "netty", "java", "html", "docker");
    boolean flag = list.stream().anyMatch(obj->obj.length()>18);
    System.out.println(flag);

	//Max Min
    Optional<User> opu = list.stream().max(Comparator.comparing(User::getAge));
    System.out.println(opu.get().getAge());

    Optional<User> opu = list.stream().max((s1,s2)->Integer.compare(s1.getAge(),s2.getAge()));
    System.out.println(opu.get().getAge());
    Optional<User> minopu = list.stream().min((s1,s2)->Integer.compare(s1.getAge(),s2.getAge()));
    System.out.println(minopu .get().getAge());

	//并⾏流parallelStream
	//顺序输出
	List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
	numbers.stream().forEach(System.out::println);
	//并⾏乱序输出
	List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
	numbers.parallelStream().forEach(System.out::println);

	//reduce 聚合操作
	//reduce 聚合操作
    Optional<T> reduce(BinaryOperator<T> accumulator);

    int result = Stream.of(1,2,3,4,5).reduce(new
     BinaryOperator<Integer>() {
         @Override
         public Integer apply(Integer item1, Integer item2) {
             return item1 + item2;
         }
     }).get();
    System.out.println("result:"+result);
	
	//聚合统计collector
    list.stream().collect(Collectors.toList());
    System.out.println(list);
	//Collectors.toMap()
	//Collectors.toSet()
	//Collectors.toCollection() :⽤⾃定义的实现Collection的数据结构收集
	//Collectors.toCollection(LinkedList::new)
	//Collectors.toCollection(CopyOnWriteArrayList::new)
	//Collectors.toCollection(TreeSet::new)
	 //joining收集器
    String str = Stream.of("springboot","springcloud","dubbo").collect(Collectors.joining(","));
    System.out.println(str);	
	
	//partitioningBy分组 
    List<String> strlist = Arrays.asList("java", "springboot", "HTML5","nodejs","CSS3");
    Map<Boolean, List<String>> result = strlist.stream().collect(partitioningBy(s -> s.length()>4));
    System.out.println(result);
     //groupingBy()分组
    Map<Integer, List<String>> slist = strlist.stream().collect(Collectors.groupingBy(o -> o.length()));
    System.out.println(slist);
    //summarizingint 集合统计
    IntSummaryStatistics summaryStatistics = strlist.stream().collect(Collectors.summarizingInt(String :: length));
    System.out.println(summaryStatistics.getMax());
    System.out.println(summaryStatistics.getAverage());
    System.out.println(summaryStatistics.getCount());
}

jdk9新特性

  1. jdk9新增的接⼝私有⽅法
  2. 增强try-with-resource
	//jdk7
	OutputStream out = new FileOutputStream(filepath);
	try(OutputStream temp = out;) {
	 	temp.write((filepath+"学习jdk新特性").getBytes());
	 }catch (Exception e){
	 	e.printStackTrace();
	 }
	//jdk9
	OutputStream out = new FileOutputStream(filepath);
	 try (out) {
		 out.write((filepath + "学习jdk新特性").getBytes());
	 } catch (Exception e) {
	 	e.printStackTrace();
	 }
  1. 增强stream,增加部分方法
  • takeWhile
    有序的集合:从 Stream 中获取⼀部分数据, 返回从头开始的尽可能多的元素, 直到遇到第⼀个false结果,如果第⼀个值不满⾜断⾔条件,将返回⼀个空的 Stream
	List<String> list = List.of("springboot","java","html","","git").stream().takeWhile(obj->!obj.isEmpty()).collect(Collectors.toList());
//⽆序集合,返回元素不固定,暂⽆⽆实际使⽤场景
	Set<String> set =Set.of("springboot","java","html","","git").stream().takeWhile(obj->!obj.isEmpty()).collect(Collectors.toList());
  • dropWhile 与 takeWhile相反,返回剩余的元素
	List<String> list =List.of("springboot","java","html","","git").stream().dropWhile(obj->!obj.isEmpty()).collect(Collectors.toList());
  1. 创建只读集合
	List<String> list = List.of("spring", "springboot", "springmvc");
	list2.remove(0);
	System.out.println(list);

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
        var listVar = new ArrayList<String>();
        System.out.println(listVar instanceof ArrayList);
        // 推断 Stream
        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
 private static final URI uri = URI.create("https://www.csdn.net/");

    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增强
 		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");
        }
  1. 多行文本块
		String html = "\n" +
                         "\n" +
                             "

Hello, world

\n"
+ "\n" + "\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`; """; }

你可能感兴趣的:(java)