JDK8新特性

一、JDK8新特性

  • 接口中默认方法+静态方法 − 默认方法就是一个在接口里面有了一个实现的方法。静态方法就是接口中有个已经使用的静态方法,可直接调用

  • Lambda 表达式(拉姆达) − Lambda 允许把函数作为一个方法的参数(函数作为参数传递到方法中)。

  • 方法引用 (Method Reference)− 方法引用提供了非常有用的语法,可以直接引用已有Java类或对象(实例)的方法或构造器。与lambda联合使用,方法引用可以使语言的构造更紧凑简洁,减少冗余代码。

    // 方法引用的代码
    System.out.println() ---> System::println();
    
  • Stream API −新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。

  • Optional 类 − Optional 类已经成为 Java 8 类库的一部分,用来解决空指针异常。

  • Date Time API − 加强对日期与时间的处理。

二、关于接口的新特性

以前接口其中一个重要特性是: 其中的方法全都是抽象方法,即都没有方法体

JDK8以后,允许接口中有被default和static修饰的方法带方法体

// 接口
interface IA {
    void test();
    // jdk8允许被default修饰的方法带方法体
    // 可以被子类对象调用
    // 也可以重写
    default void test2(){
        System.out.println("默认方法执行" );
    }

    // jdk8允许被static修饰的方法带方法体
    // 通过接口名直接调用
    static void test3(){
        System.out.println("静态方法" );
    }
}

class AImpl implements IA{

    @Override
    public void test() {
    }

    @Override
    public void test2() {

    }
}

三、Lambda表达式[重点]

Lambda 允许把函数(方法)作为一个方法的参数(函数作为参数传递到方法中)。


其实就是简化了匿名内部类的写法,更准确的说是对接口方法的重写的简化

3.1 初识lambda

package com.qf.jdk.lambda;

public class Demo1Lambda {

    public static void main(String[] args) {
        // 1 之前使用匿名内部类,开启线程
        new Thread(new Runnable( ) {
            @Override
            public void run() {
                System.out.println("匿名内部类开启线程" );
            }
        }).start();

        // 以上代码,主要关注的是线程的执行任务,即run()内部的代码

        // 2 换成lambda后
        new Thread(() -> System.out.println("lambda开启线程" )).start();

        // lambda基本结构是
        // () -> 语句
        // 参数列表,箭头符号,执行语句
        
        // 总结: lambda关注的是方法,且是方法的参数列表和方法体
        // 不管类名,方法名等信息
        // 是将方法简写成() -> {} 形式传给另外一个方法
    }
}

3.2 语法特点

能够写成lambda形式的的前提是

  1. 方法得有参数
  2. 参数的必须是接口
  3. 接口中的方法有且只能有一个!!!
总结: lambda就是对接口的抽象方法重写实现

例如: Thread(Runable run) 这个构造方法
1)Thread构造方法有参数
2)参数Runnable是接口
3)且Runnable接口内只有一个方法run
所以可以给这个Thread()构造方法内的代码改写成lambda形式

语法特征

(参数) -> {执行语句}
或者
参数  -> 执行语句
  • 参数圆括号,当参数是一个的时候,圆括号可加可不加

    • (x) -> System.out.println(x)
    • x -> System.out.println(x)
  • 参数圆括号,当参数是多个的时候,圆括号必须加

    • (x,y) -> System.out.println(x+y)
  • 参数数据类型可写可不写,编译时会自动推断是什么类型

    • (x,y) -> System.out.println(x+y)
    • (int x,String y) -> System.out.println(x+y)
  • 执行语句的花括号,当且仅当执行语句只有一句时,可以不加花括号

    • new Thread(() -> System.out.println("匿名内部类开启线程")).start();
      
  • 执行语句的花括号,当执行语句不只一句时,必须加花括号

    • new Thread(() -> {
               int a = 1;
               a++;
               System.out.println("lambda开启线程" );
           }).start();
      
  • 关于返回值

    • 如果方法有返回值,且执行语句只有一行语句时,可以不用写return,直接写值

      test(() -> return 1);
      test(() -> 1);// 1就是return1
      
    • 如果代码比较多,又要返回数据,就必须写上return

      test(() -> {
      	int a = 1;
      	a++;
      	return a;
      });
      
public class Demo3 {


    public static void main(String[] args) {
        // 无参数的lambda,()不能省略
        test(() -> {
            System.out.println("show()" );
        });

        // 有参数的lambda,可以加()
        // test2((int x) -> {
        //             System.out.println(x );
        //         }
        // );
        // 也可以不写数据类型
        // test2((x) -> {
        //             System.out.println(x );
        //         }
        // );
        // 甚至可以省略小括号
        test2(x -> {
                    System.out.println(x );
                }
        );
        // 如果lambda参数有多个,可以省略数据类型,但不能省略括号
        test3((a,s) -> {});

        // lambda方法体只有一个执行语句时,可以省略{}
        test(()-> System.out.println("xxxx" ));
        // lambda方法体有多个执行语句时,不可以省略{}
        test(()-> {
            int a = 1;
            a = 2;
        });


        // lambda内可以写return 返回数据
        test4(() -> {
            int a = 1;
            a = 2;
            return a;
        });

        // 如果lambda比较简单,方法体内只有一句return
        // 此时省略{}和return,直接写值
        // test4(() -> {
        //     return 2;
        // });
        test4(()-> 2);// 2就是返回值
    }

    // 定义方法,且方法有参数,是接口
    public static void test(IA ia){
        ia.show();
    }

    public static void test2(IB ia){
        ia.show(1);
    }

    public static void test3(IC ia){
        ia.show(1,"");
    }
    public static void test4(ID ia){
        ia.show();
    }
}
// 接口
interface IA {
    // 无参无返回值
    void show();
}
interface IB {
    // 有参无返回值
    void show(int a);
}
interface IC {
    // 多个参无返回值
    void show(int a,String s);
}
interface ID {
    int show();
}

3.3 练习

 /*
 * @desc 使用lambda改写之前的代码
 *
 * 什么时候用lambda?
 *
 * 当调用一个方法,发现方法的参数列表是接口
 * 点击接口查看,如果发现接口内部方法只有一个
 * 此时,就可以将这个方法改写成lambda
 *
 */
public class Demo4 {

    public static void main(String[] args) {

        // 创建线程
        new Thread(() -> System.out.println("线程任务" )).start();

        // 创建线程池
        // ExecutorService pool = Executors.newFixedThreadPool(3);
        // // 线程池执行任务
        // pool.execute(() -> {
        //     for (int i = 0; i < 100; i++) {
        //         System.out.println(i );
        //     }
        // });
        // pool.shutdown();


        // 集合工具Collections
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(3);
        list.add(1);
        list.add(4);
        list.add(2);
        System.out.println(list );
        //Collections.sort(list);// 默认按照升序排序
        // System.out.println(list );

        //Collections.sort(list,(o1,o2) ->  o1 - o2);// 升序
        Collections.sort(list,(o1,o2) ->  o2 - o1);// 升序
        System.out.println(list );
    }
}

3.4 总结

  • lambda就是简化了匿名内部类的写法
  • lambda其实就是接口方法的重写
  • lambda的参数和返回值是根据接口方法决定的

四、函数式接口

接口中只有一个抽象方法时,该接口就是函数式接口.

为什么叫做函数式接口?因为这种接口,放在方法中当参数时,可以改造成lambda,进行运算.


Java提供了一个注解可以校验接口是否是函数式接口

@FunctionalInterface

Java中提供了几个特别常用的函数式接口

  • Supplier 供应,即返回一个数据 (无参有返回值的方法)
  • Consumer 消费,即给其传入数据做运算 (有参无返回值的方法)
  • Function 函数,传入2个参数,用于转换数据的 (有参有返回值的方法)
  • Predicate 判断,返回时boolean (有参,返回值是boolean)

4.1 Supplier

JDK中Supplier.java源码

@FunctionalInterface
public interface Supplier<T> {

    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}
// 该接口用来返回一个数据,所以叫供应商
// 其实就是无参数有返回值的接口,用的时候就是无参有返回值的lambda

练习,设计方法,通过Supplier接口,获得字符串的长度

    public static void main(String[] args) {

        String str = "java";

        // 获得字符串长度
        get(() -> str.length());
    }

    public static void get(Supplier<Integer> sup`plier){
        Integer n = supplier.get();
        System.out.println(n);
    }

4.2 Consumer

JDK中Consumer.java源码

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     * 给传入一个值,对该值进行操作
     * @param t the input argument
     */
    void accept(T t);
}
// 其实就是有参数无返回值的接口,用的时候就是有参无返回值的lambda

练习:设计方法,传入字符串,将字符串全部转大写,后输出

public class Demo1_Consumer {

    public static void main(String[] args) {
        // 将传入的字符串转大写后输出
        show("java",(s) -> {
            String s1 = s.toUpperCase( );
            System.out.println(s1 );
        });

        show("java",(s) -> System.out.println(s.toUpperCase( ) ));

      // 将传入的数字,变成立方结果后输出
        show2(10,(i) -> System.out.println(Math.pow(10,3)));

    }

    // 消费,就是传入一个数据,对其进行处理
    public static void show(String s,Consumer<String> c) {
        c.accept(s);
    }

    public static void show2(Integer i,Consumer<Integer> c) {
        c.accept(i);
    }
}

4.3 Function

JDK中Function.java源码

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
// 该接口用于,转换数据
// 其实就是有参数有返回值的接口,用的时候就是有参有返回值的lambda

练习,设计方法,将传入的字符串数字,转为整形数字

package com.qf.function_interface;

import java.util.function.Function;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo2_Function {

    public static void main(String[] args) {
        show(2,(t) -> String.valueOf(t * 10));
    }

    // Function接口,主要是用于接收数据,处理数据后返回
    // 将传入的数字放大10倍后变为字符串返回
    public static void show(Integer t,Function<Integer,String> f){
        String i = f.apply(t);
        System.out.println(i);
    }
}

4.4 Predicate

JDK中Predicate.java源码

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}

判断数据是否是偶数

   public static void main(String[] args) {
        // show4((n) -> {
        //     if (n % 2 == 0) {
        //         return true;
        //     }else{
        //         return false;
        //     }
        // });

        show4((n) -> n % 2 == 0 ? true: false);

    }
   public static void show4(Predicate<Integer> p) {
        boolean test = p.test(2);
        System.out.println("是否是偶数:" + test );
    }

4.5 总结

这些函数式即可,一般是用在下面Stream流中的

现在学习这几个函数式接口,就是让大家知道这些接口特性:

  • 比如有无参数,参数类型和个数
  • 比如有无返回值,返回值类型

以及用法,就是这些接口一般都会用在哪种场景下?

  • Supplier接口的方法一般用于 获得数据
  • Consumer接口的方法 一般用于 处理数据
  • Function接口的方法一般用于 转换数据
  • Predicate接口的方法一般用于 判断数据

五、Stream流[重点]

Stream流,不要和之前学的IO流进行联想,他们之间没有关系.

IO流,数据像水流一样在传输,即IO流强调是传输数据

Stream流,数据像车间流水线,在一直往下走动,不是保存数据,也不纯粹的传输数据,而是像车间流水线一样,在处理数据.

5.1 获得流

Java提供了几种方式,可以让我们获得Stream流

  1. [集合创建流]Collection 接口的 stream()或 parallelStream()方法
  2. [自由值创建]静态的 Stream.of(…)、Stream.empty()方法
  3. [数组创建流]Arrays.stream(array)
  4. 静态的 Stream.generate()方法生成无限流,接受一个不包含引元的函数
  5. 静态的 Stream.iterate()方法生成无限流,接受一个种子值以及一个迭代函数
  6. Pattern 接口的 splitAsStream(input)方法
  7. 静态的 Files.lines(path)、Files.lines(path, charSet)方法
  8. 静态的 Stream.concat()方法将两个流连接起来
package com.qf.stream;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 演示获得流
 */
public class Demo2 {

    public static void main(String[] args) {
        // Collection接口在JDK1.8以后,加入了一个新的方法stream()
        // 该方法就可以将集合转成流
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        Stream<Integer> stream = list.stream( );

        // jdk1.8后,提供了Stream接口,其中有个静态方法
        Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5);

        // Arrays类也有了新的方法
        int[] arr = {11,22,33,44,55};
        IntStream stream3 = Arrays.stream(arr);
    }
}

5.2 Stream操作

Stream流就是流式处理数据,流的操作有很多种

  • 中间操作(真正处理数据的操作)
    • 中间操作就是执行完返回的是一个流,即可以继续执行流操作
    • 敲代码来说,就是使用中间操作的方法,写完继续再.调用其他方法
  • 终止操作(将操作完的结果返回)
    • 敲代码来说,调用终止方法,代码就结束;
操作函数说明
中间操作filter(Predicate)将结果为false的元素过滤掉
中间操作map(Function)转换元素的值,可以用方法引元或者lambda表达式
中间操作flatMap(Function)若元素是流,将流摊平为正常元素,再进行元素转换(合并两个流为一个流)
中间操作limit(long n)保留前n个元素
中间操作skip(long n)跳过前n个元素
中间操作concat(Stream s1, Stream s2)将两个流拼接起来
中间操作distinct()剔除重复元素
中间操作sorted()将Comparable元素的流排序
中间操作sorted(Comparator)将流元素按Comparator排序
中间操作peek(Consumer)流不变,但会把每个元素传入fun执行,可以用作调试
终结操作max(Comparator)取最大值
终结操作min(Comparator)取最小值
终结操作count()统计元素数量
终结操作findFirst()获得流的第一个元素
终结操作findAny()返回任意元素
终结操作anyMatch(Predicate)任意元素匹配时返回true
终结操作allMatch(Predicate)所有元素匹配时返回true
终结操作noneMatch(Predicate)没有元素匹配时返回true
终结操作reduce(Function)从流中计算某个值,接受一个二元函数作为累积器,从前两个元素开始持续应用它,累积器的中间结果作为第一个参数,流元素作为第二个参数
终结操作iterator()迭代器迭代元素
终结操作forEach(Consumer)lambda的方式迭代
终结操作forEachOrdered(Consumer)可以应用在并行流上以保持元素顺序

5.2.1 中间操作

下面演示流的操作使用 - 中间操作

package com.qf.jdk.stream;

import java.util.stream.Stream;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 操作流
 */
public class Demo4 {

    public static void main(String[] args) {
        // 1 获得流
        Stream<String> stream = Stream.of("11", "11","22","22", "33");
        Stream<String> stream2 = Stream.of("aa", "bb", "cc");
        // 2 limit(long n) 保留流里面的前几个
        // stream.limit(2).forEach(s -> System.out.println(s ));

        // 3 skip(long n) 跳过前几个
        // stream.skip(2).forEach(s -> System.out.println(s ));

      
        // 5 distinct 将流中的数据去重
        // stream.distinct().forEach(s -> System.out.println(s ));

        // 6 sorted 排序,默认是升序
        Stream<Integer> stream3 = Stream.of(5,3,2,1,4);
        // stream3.sorted().forEach(s -> System.out.println(s ));

        stream3.sorted((o1,o2) -> o2 - o1).forEach(s -> System.out.println(s ));
        
        // 7 filter筛选数据
        // 获得集合
        List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
        // 集合得到流,再通过filter过滤数据,最后collect收集数据返回过滤后的数据存入集合
List<Integer> collect = integerList.stream().filter(i -> i > 3).collect(Collectors.toList());
        // 打印集合
        System.out.println(collect);
        
         // 8 map,映射数据
        // 获得集合
        List<String> stringList = Arrays.asList("zhangsan", "lisi",  "wangwu", "haha");
        // 集合得到流,然后使用map映射数据,传入集合中的元素,计算数据长度,最后收集到List集合
        List<Integer> collect = stringList.stream( ).map(item -> item.length( )).collect(Collectors.toList( ));
        // 打印结果,是上面集合数据的长度集合[8, 4, 6, 4]
        System.out.println(collect );
    }

}

5.2.2 终止操作

下面演示流的操作使用 - 终止操作

package com.qf.jdk.stream;

import jdk.nashorn.internal.ir.IfNode;

import java.util.Iterator;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo5 {

    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(5, 3, 2, 1, 4);

        // 1 终止操作min,返回的是Optional类
        // Optional类中有个方法,get() ,可以获得其中的数据
        // min方法返回的是,排序后的第一个
        Optional<Integer> optional = stream.min((o1, o2) -> o1 - o2);
        Integer min = optional.get( );
        System.out.println(min );

        Integer min = stream.min((o1, o2) -> o1 - o2).get( );

        // 2 count() 计数
        System.out.println(stream.count( ));
        long count = stream.filter(e -> e > 2).count( );
        System.out.println(count );

        // 3 findFirst() 获得流里面第一个,返回Optional
        System.out.println(stream.findFirst( ).get( ));

        // 4 forEach()  迭代器迭代元素
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.forEach(s -> System.out.println(s ));
    }
}

练习:

/*
给定ArrayList<Integer>集合,
先过滤数据只保留偶数,
后对数据进行降序排序,
去除重复元素,
将元素转成String类型
后返回一个ArrayList<String>
*/
ArrayList<Integer> list4 = new ArrayList<>( );        
list4.add(1);
list4.add(2);
list4.add(2);
list4.add(3);
list4.add(3);
list4.add(4);
list4.add(4);

List<String> collect2 = list4.stream( )
    .filter(e -> e % 2 == 0)
    .sorted((o1, o2) -> o2 - o1)
    .distinct( )
    .map(e -> String.valueOf(e))
    .collect(Collectors.toList( ));

5.2.3 注意事项

Stream流的操作注意事项

  1. 流的操作只能使用一次
  2. 使用中间操作,返回新的流
  3. 没有终止操作,就不会有结果,换句话说,没有终结操作,中间操作是 不会执行的
package com.qf.stream;

import java.util.ArrayList;
import java.util.stream.Stream;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo3 {

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        Stream<Integer> stream = list.stream( );

        // 流第一次用
        // stream.forEach((s) -> System.out.println(s ));
        // 第二次再用报错!! 流只能使用一次!!
        // stream.forEach((s) -> System.out.println(s ));


        // 中间操作会返回新的流
        // 没有终止操作,中间操作不会执行
        Stream<Integer> stream1 = stream.filter((x) -> {
            System.out.println("正在过滤..."+x );
            return x % 2 == 0;
        });
        stream1.forEach((x) -> System.out.println(x ));
    }
}

5.3 流的收集

流操作完,将数据流中的数据再返回成数组和集合 --> 这就是收集流

将流收集到集合或数组中

  • collect() 收集到集合
  • toArray 收集到数组
package com.qf.jdk.stream;

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
public class Demo6 {

    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(5, 5,3, 2, 1, 4,4);

        // 流中数据转成list集合
        // List<Integer> list = stream.filter(i -> i > 3).collect(Collectors.toList( ));
        // System.out.println(list );

        // 流中数据转成set集合
        // Set<Integer> set = stream.filter(i -> i > 3).collect(Collectors.toSet( ));
        // System.out.println(set );

        // 流可以转成数组
        // Object[] array = stream.toArray( );

        // 也可转成指定类型的数组
        Integer[] array = stream.toArray((length) -> new Integer[length]);
        System.out.println(Arrays.toString(array));
    }
}

六、新日期API

Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
/*一些吐槽:
1.java.util.Date被设计为日期 + 时间的结合体。也就是说如果只需要日期,或者只需要单纯的时间,用Date是做不到的。
2. 年要减1900…  月从0-11 …
3.	Date是可变的,也就是说我把一个Date日期时间对象传给方法,方法内竟然还能更改
*/
@Test 
public void test() { 
    Date currDate = new Date(); 
    System.out.println("当前日期是①:" + currDate); 
    boolean holiday = isHoliday(currDate); 
    System.out.println("是否是假期:" + holiday); 
 
    System.out.println("当前日期是②:" + currDate); 
} 
 
/** 
 * 是否是假期 
 */ 
private static boolean isHoliday(Date date) { 
    // 假设等于这一天才是假期,否则不是 
    Date holiday = new Date(2021 - 1900, 10 - 1, 1); 
 
    if (date.getTime() == holiday.getTime()) { 
        return true; 
    } else { 
        // 模拟写代码时不注意,使坏 
        date.setTime(holiday.getTime()); 
        return true; 
    } 
}

日期

LocalDate

	@Test
	public void test02() {
		// ========== 获得日期 ==========
		// 获得当前日期
		LocalDate now = LocalDate.now();
		System.out.println(now);
		// 获得指定日期的时间
		LocalDate date = LocalDate.of(2020, 1, 1);
		System.out.println(date);
		
		// 获得年
		System.out.println(now.getYear());
		// 获得月
		System.out.println(now.getMonthValue());
		// 获得日
		System.out.println(now.getDayOfMonth());
		
		// ========== 设置日期 ==========
		// 设置之后返回的日期是一个新的日期对象,之前的日期并未更改
		// 设置年
		LocalDate withYear = now.withYear(1990);
		// 设置月
		LocalDate withMonth = now.withMonth(8);
		// 设置日
		LocalDate withDayOfMonth = now.withDayOfMonth(8);
		System.out.println(now);
		System.out.println(withYear);
		// 增加日期,返回新的日期对象
		// 增加的方法plusXxx()
		LocalDate plusYears = now.plusYears(2);
		
		// 减少日期
		// 减少的方法 minusXxx()
		LocalDate minusYears = now.minusYears(2);

	}

时间

LocalTime

	@Test
	public void test03() {
		// ========== 获得时间 ==========
		// 获得当前时间
		LocalTime now = LocalTime.now();
		System.out.println(now);
		// 获得指定时间
		LocalTime of1 = LocalTime.of(10, 10); // 时分
		LocalTime of2 = LocalTime.of(10, 10,10);// 时分秒
		LocalTime of3 = LocalTime.of(10, 10,10,10);// 时分秒纳秒
		System.out.println(of1);
		
		// 获得时,分,秒
		System.out.println(now.getHour());
		System.out.println(now.getMinute());
		System.out.println(now.getSecond());
		
		// ========== 设置时间 ==========
		// 设置时
		LocalTime hour = now.withHour(8);
		// 设置分
		LocalTime minute = now.withMinute(8);
		// 设置秒
		LocalTime second = now.withSecond(8);
		System.out.println(now);
		System.out.println(hour);
				
        // 增加时间,返回新的时间对象
		// 增加的方法plusXxx()
		LocalTime plus = now.plusHours(2);
		
		// 减少时间
		// 减少的方法 minusXxx()
		LocalTime minus = now.minusHours(2);
	}

日期时间

LocalDateTime

	@Test
	public void test04() {
		// ========== 获得日期时间 ==========
		// 获得当前时间
		LocalDateTime now = LocalDateTime.now();
		System.out.println(now);
		// 获得指定时间
		LocalDateTime of1 = LocalDateTime.of(1900, 1, 1, 10, 10); //年月日时分
		LocalDateTime of2 = LocalDateTime.of(2000, 10,10,8,8,8);// 年月日时分秒
		System.out.println(of1);
		
		// 获得年,月,日
		System.out.println(now.getYear());
		System.out.println(now.getMonthValue());
		System.out.println(now.getDayOfMonth());
		// 获得时,分,秒
		System.out.println(now.getHour());
		System.out.println(now.getMinute());
		System.out.println(now.getSecond());
		
		// ========== 设置日期时间 ==========
		// 设置时
		LocalDateTime hour = now.withHour(8);
		// 设置分
		LocalDateTime minute = now.withMinute(8);
		// 设置秒
		LocalDateTime second = now.withSecond(8);
		System.out.println(now);
		System.out.println(hour);

		// 增加时间,返回新的时间对象
		// 增加的方法plusXxx()
		LocalDateTime plus = now.plusHours(2);
		
		// 减少时间
		// 减少的方法 minusXxx()
		LocalDateTime minus = now.minusHours(2);

		System.out.println(now.isAfter(plus));
		System.out.println(now.isBefore(plus));
		System.out.println(now.isEqual(plus));
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Su sir~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值