學習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<? extends T> other)
方法3:orElseThrow(Supplier<? extends X> 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<? super T, ? extends U> 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<? super T, ? extends U>,而flapMap的入參類型爲Function<? super T, Optional>

5> filter(Predicate<? super T> 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>

  • 傳⼊⼀個值經過函數的計算返回另⼀個值
  • 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<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
 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 = "<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`;
                       """;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章