zoukankan      html  css  js  c++  java
  • JavaSE:第十六章:java8新特性

    ##java8内容
    1.Lambda表达式 ★
    2.函数式接口 ★
    3.方法引用 ★
    4.构造器引用|数组引用 ★
    5.StreamAPI ★
    6.接口中可以定义默认方法和静态方法 ★
    7.Optional类的引入:为了减少空指针异常【了解】
    8.新日期API【了解】
    9.重复注解【了解】
    10.Nashone引擎的使用:在jvm上运行js【后面课程】

    ##Java8引进
    1995年推出jdk1.0
    04年推出 jdk5 ,改革非常大
    06年推出 jdk6 ,企业中使用的最长久版本
    --------被Oralce公司收购-----------
    11年 推出 jdk7
    14年 推出 jdk8 LTS版本:受商业公司支持的长期版本
    17年 9月份推出 jdk9, “六个月版本升级计划” 小版本
    18年 3月份 推出jdk10 小版本
    18年 9月份 推出jdk11 LTS版本:

    ##Lambda表达式
    ###理解
    理解成一段可以传递的代码,作为函数式接口的实例出现
    ###应用场景
    示例1:
    接口 a = Lambda表达式;

    示例2:【居多】
    method(Lambda表达式);
    public void method(接口 a){
    }
    ###好处
    1、语句更加简洁
    2、更加紧凑,使java语言的表达能力得到了提升!
    ###语法 ★
    (参数类型 参数名,参数类型 参数名)->{方法体的实现/Lambda体}
    示例:
    (String o1, String o2)->{return o1.compareTo(o2);}
    特点:
    ①左侧参数列表中的参数类型可以省略!
    ②如果左侧参数列表中,只有一个参数,则小括号也可以省略
    ③右侧的Lambda体中如果仅有一句话,则大括号可以省略
    ④右侧的Lambda体中仅有的一句话为return语句,则return要求省略
    ##函数式接口
    理解:
    只有一个抽象方法的接口,称为函数式接口
    Consumer消费型接口
    Supplier供给型接口
    Function<T,R>函数型接口
    Predicate 断定型接口

    ##方法引用
    ###理解
    * 方法引用实质上就是Lambda表达式的简化,同样可以作为函数式接口的实例出现
    * 能用方法引用 的肯定能用Lambda表达式
    * 能用Lambda表达式的不一定能用方法应用,除非满足以下要求:
    ###要求:
    ①Lambda体中仅仅只有一句话
    ②仅有的一句话为 方法调用!
    ③调用方法的参数列表和Lambda体实现的抽象方法的参数列表一致!
    调用方法的返回类型和Lambda体实现的抽象方法的返回类型一致!
    特例:类名::普通方法
    调用方法的调用者正好是 抽象方法的第一个参数,并且其他参数一致
    调用方法的返回类型和抽象方法的返回类型一致!
    ###语法:
    类名或对象::方法名
    ###情况:
    * 1、对象::普通方法
    * 2、类名::静态方法
    * 3、类名::普通方法
    ##关于方法引用、数组引用、构造器引用的总结
    1.能使用方法引用|数组引用|构造器引用的地方,肯定能用Lambda表达式!
    2.能用Lambda表达式的地方,不一定能用方法引用|数组引用|构造器引用,必须满足以下条件
    3.能使用Lambda表达式的地方,肯定能用匿名内部类
    能用匿名内部类的,不一定能用Lambda表达式,必须满足:
    实现的接口为 函数式接口(里面只有一个抽象方法的接口)!
    方法引用:
    ①Lambda体只有一句话
    ②仅有的一句话为调用方法
    ③方法的参数列表、返回类型正好与抽象方法的参数列表、返回类型一致!
    特殊:如果是类名::普通方法,则要求方法的调用者为抽象的方法的第一个参数,其他一致

     此类用于演示方法引用
     *  举例:
     *     匿名内部类:
     *   	UnaryOperator<Double> up = new UnaryOperator<Double>(){
     *   		public Double apply(Double t){
     *            return Math.sqrt(t);
     *          }
     *     };
     *     Lambda:
     *     UnaryOperator<Double> up =d->Math.sqrt(d);
     *     方法引用:
    	   UnaryOperator<Double> up = Math::sqrt;
     */
    public class TestMethodRef {
    	//1、对象::普通方法
    	@Test 
    	public void test1_1() {
    		//匿名内部类
    //		Runnable r = new Runnable() {
    //			@Override
    //			public void run() {
    //				System.out.println();
    //			}
    //		};
    		//方法引用
    		Runnable r2 = System.out::println;
    		r2.run();
    	}
    	//对象::普通方法
    	@Test 
    	public void test1_2() {
    		//匿名内部类
    //		Consumer<String> con = new Consumer<String>() {
    //			@Override
    //			public void accept(String t) {
    //				System.out.println(t);
    //				
    //			}
    //		};
    		//方法引用
    		Consumer<String> con2 = System.out::println;
    		con2.accept("赵丽颖和冯绍峰已经结婚了");
    	}
    	//2、类名::静态方法
    	@Test 
    	public void test2() {
    		//匿名内部类
    		Comparator<Double> com = new Comparator<Double>() {
    			@Override
    			public int compare(Double o1, Double o2) {
    				return Double.compare(o1, o2);
    			}
    		};
    		//Lambda
    		Comparator<Double> com1 = (o1,o2)->Double.compare(o1, o2);
    		//方法引用
    		Comparator<Double> com2 =Double::compare;
    	}
    	//3、类名::普通方法
    	@Test 
    	public void test3() {
    		//匿名内部类
    //		Function<Employee,String> fun = new Function<Employee,String>(){
    //			@Override
    //			public String apply(Employee t) {
    //				return t.getName();
    //			}
    //		};
    		//方法引用
    		Function<Employee,String> fun2 = Employee::getName;
    		System.out.println(fun2.apply(new Employee("张无忌", 12, 1000, '男')));
    	}
    	//3、类名::普通方法
    	@Test 
    	public void test3_2() {
    		//匿名内部类
    //		BiFunction<String, String, Boolean>  bf = new BiFunction<String, String, Boolean>() {
    //			@Override
    //			public Boolean apply(String t, String u) {
    //				return t.equals(u);
    //			}
    //		};
    		//方法引用
    		BiFunction<String, String, Boolean>  bf2 = String::equals;
    		System.out.println(bf2.apply("hello", "Hello"));
    	}
    }
    

    构造器引用

    理解:构造器引用本质上就是Lambda表达式,只是语句更加简洁。作为函数式接口的实例,一般作为参数传递给方法!
    能用构造器引用的地方,肯定能用Lambda表达式
    但能用Lambda表达式的地方,不一定能用构造器引用

    要求:
    ①Lambda体中仅仅只有一句话
    ②仅有的一句话为调用构造器 new ClassName(实参列表);
    ③抽象方法的参数列表和构造器的参数列表完全一致
    抽象方法的返回类型为构造器所属的类型。

    语法:
    类名::new

     此类用于演示构造器引用
    public class TestConstructorRef {
    	//案例1:返回new String();
    	@Test 
    	public void test1() {
    		//匿名内部类
    //		Supplier<String> sup = new Supplier<String>() {
    //			@Override
    //			public String get() {
    //				return new String();
    //			}
    //		};
    		//构造器引用
    		Supplier<String> sup2 = String::new;
    		int length = sup2.get().length();
    		System.out.println(length);
    	}
    	//案例2:返回new StringBuffer(int capacity);
    		@Test 
    		public void test2() {
    			Function<Integer,StringBuffer> fun = new Function<Integer,StringBuffer>(){
    				@Override
    				public StringBuffer apply(Integer t) {
    					return new StringBuffer(t);
    				}
    			};
    			Function<Integer,StringBuffer> fun2 = StringBuffer::new;
    		}
    		//案例3:返回new Employee("段誉", 22, 10000, '男')
    		@Test 
    		public void test3() {
    			A<String,Integer,Double,Character,Employee> a1 = (s,i,d,c)->new Employee(s,i,d,c);
    			A<String,Integer,Double,Character,Employee> a = Employee::new;
    		}
    }
    interface A<T,R,U,M,N>{
    	N test(T t,R r,U u,M m);
    }
    

    数组引用
    理解:数组引用本质上就是Lambda表达式,只是语句更加简洁。作为函数式接口的实例,一般作为参数传递给方法!

    能用数组引用的地方,肯定能用Lambda表达式
    但能用Lambda表达式的地方,不一定能用数组引用
    要求:
    ①Lambda体仅仅有一句话
    ②仅有的一句话为返回一个新数组 new 数组类型[长度];
    ③抽象方法的参数只有一个,就是数组的长度;抽象方法的返回为创建的新数组类型
    语法:
    数组类型[]::new

    此类用于演示数组引用
    public class TestArrayRef {
    	//案例1:返回一个String[] s = new String[5]
    	@Test 
    	public void test1() {
    		//匿名内部类
    //		Function<Integer,String[]>  fun = new Function<Integer,String[]>(){
    //			@Override
    //			public String[] apply(Integer t) {
    //				return new String[t];
    //			}
    //		};
    		//数组引用
    		Function<Integer,String[]>  fun2 = String[]::new;
    		String[] arr = fun2.apply(5);
    		for (String string : arr) {
    			System.out.println(string);
    		}
    	}
    	//案例2:返回一个Employee[]
    	@Test 
    	public void test2() {
    		Function<Integer,Employee[]> fun = Employee[]::new;
    		Employee[] apply = fun.apply(3);
    		for (Employee employee : apply) {
    			System.out.println(employee);
    		}
    	}
    }
    

    综述:匿名内部类》Lambda表达式》方法引用|数组引用|构造器引用

    ##StreamAPI

    ###好处
    1、更高效
    2、易于使用,提供了丰富强大的方法。

    ###使用步骤
    1.开始操作(√)
    说明:创建Stream对象,指向一个具体的数据源(集合、数组、一系列值、无线流)
    2.中间操作(可选 0——n)
    说明:对数据源数据的计算、处理
    3.终止操作(√)
    说明:想要一个结果(打印、计数、去最值等)

    ###使用特点

    1、Stream讲究的是“计算”,可以处理数据,但不能更新源数据
    
    2、Stream 属于“惰性操作”,必须等待终止操作执行后,前面的中间操作或开始操作才会处理
    
    3、Stream只能消费一次,一旦消费,就不能再次使用,除非重新创建Stream对象
    
    4、Stream的中间操作可以有0个或多个,每个操作都会返回一个新的Stream
    
    5、Stream相当于一个 更强大的Iterator,可以处理更加复杂的数据,并且实现并行化,效率更高!
    

    ###开始操作的相关API
    一、通过集合来获取Stream对象 ★
    Stream stream = list.stream();
    二、通过数组来获取Stream对象
    Stream stream = Arrays.stream(数组);
    三、通过一组指定的值来获取Stream对象
    Stream stream = Stream.of(T…ts)
    四、生成无限流
    Stream stream= Stream.generate(Supplier sup);

    /**
     * 此类用于演示Stream的使用步骤一:创建Stream对象
     * 引申:
     * Stream的使用步骤
     * 1、创建Stream对象,指向数据源
     * 2、中间操作,处理数据,返回一个新的Stream
     * 3、终止操作,执行
     * 创建Stream对象的方式
     * 1、通过集合对象创建Stream
     * 2、通过数组对象创建Stream
     * 3、通过一系列值创建Stream
     * 4、生成无限流
     */
    public class TestStreamStart {
    	// 1、通过集合对象创建Stream ★
    	@Test 
    	public void test1() {
    		List<Employee> list = EmployeeData.getData();//集合
    		//获取串行流对象stream
    		Stream<Employee> stream = list.stream();
    		//获取并行流对象parallelStream
    //		Stream<Employee> parallelStream = list.parallelStream();
    		//补充:终止操作
    		stream.forEach(System.out::println);
    	}
    	// 2、通过数组对象创建Stream
    	@Test 
    	public void test2() {
    		Stream<String> stream = Arrays.stream(new String[] {"白眉鹰王","青易斧王","紫衫龙王","金毛狮王"});
    		stream.forEach(System.out::println);
    	}
    	// 3、通过一系列值创建Stream
    	@Test 
    	public void test3() {
    		Stream<String> of = Stream.of("周芷若","小昭","殷离","赵敏");
    		of.forEach(System.out::println);
    	}
    	// 4、生成无限流
    	@Test 
    	public void test4() {
    		Stream<Double> stream = Stream.generate(Math::random);
    		stream.forEach(System.out::println);
    	}
    	//案例:演示链式调用(流式编程)
    	@Test 
    	public void exec1() {
    		//测试1
    //		EmployeeData.getData().stream().forEach(System.out::println);
    		//测试2
    		Person p = new Person();
    //		p.eat();
    //		p.sleep();
    //		p.play();
    //		p.study();
    		p.eat().sleep().play().study();
    	}
    }
    class Person{
    	public Person eat() {
    		System.out.println("吃");
    		return this;
    	}
    	public Person sleep() {
    		System.out.println("睡");
    		return this;
    	}
    	public Person play() {
    		System.out.println("玩");
    		return this;
    	}
    	public Person study() {
    		System.out.println("学");
    		return this;
    	}
    }
    

    ###中间操作的相关API
    * filter(Predicate):根据条件过滤
    * limit(long max):截取size<=max的元素
    * skip(long s):跳过前s个
    * distinct():返回去重后的元素集合,根据hashCode和equals方法判断重复项
    * map(Function):映射成新元素
    * flatMap(Function):映射成Stream类型的新元素
    * sorted():自然排序
    * sorted(Comparator):定制排序
    *

    /**
     * 此类用于演示Stream的使用步骤二:中间操作
     * 特点:
     * ①每个中间操作方法,都会返回一个持有结果的新的Stream对象
     * ②中间操作是“惰性求值”,必须等待终止操作后,才会有处理结果
     * ③Stream是一次性消费,每次消费后,则不能再次消费,除非重新创建新的Stream
     * ④中间操作可以实现链式调用!
     * 常见方法:
     * filter(Predicate):过滤
     * skip(n):去掉前几项
     * limit(n):获取前n项
     * distinct():去重
     * map(Function):映射
     * flatMap(Function):映射,返回Stream
     * sorted():自然排序,要求元素本身实现Comparable接口
     * sorted(Comparator):定制排序
     */
    public class TestStreamMiddle {
    	List<Employee> list;
    	@Before 
    	public void before() {
    		 list = EmployeeData.getData();
    	}
    	/*
    	 * 筛选与切片
    	 *  filter(Predicate p)——接收 Lambda , 从流中排除某些元素。
    		limit(n)——截断流,使其元素不超过给定数量。
    		skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
    		distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
    	 */
    	@Test 
    	public void test1() {
    		//1.创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作
    		//方式一:filter过滤
    //		Stream<Employee> filter = stream.filter(t->t.getGender()=='男');
    		//方式二:limit限制,返回不超过指定条目数的数据
    //		Stream<Employee> limit = stream.limit(5);
    		//方法三:skip(n),跳过指定的n条数据
    //		Stream<Employee> skip = stream.skip(3);
    		//方法四:distinct()去重:两个元素通过equals判断,如果返回true,则为重复项,一般往往需要重写元素的equals和hashCode方法
    		Stream<Employee> distinct = stream.distinct();
    		//3.终止操作
    		distinct.forEach(System.out::println);
    	}
    	/**
    	 * 映射
    	 * map:映射(将元素映射成任意类型)
    	 * flatMap:映射(将元素映射成Stream类型)
    	 */
    	@Test 
    	public void test2() {
    		//1.创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作
    		//方法5:map
    //		Stream<String> map = stream.map(Employee::getName);
    //		Stream<String> filter = map.filter(s->s.contains("段"));
    		Stream<Stream<Object>> map = stream.map(TestStreamMiddle::fromEmployeeToStream);
    		//方法6:flatMap
    //		Stream<Object> flatMap = stream.flatMap(TestStreamMiddle::fromEmployeeToStream);
    		//3.终止操作
    //		filter.forEach(System.out::println);
    		map.forEach(System.out::println);
    	}
    	/*
    	 * 排序
    	 * sorted()——自然排序
    	   sorted(Comparator com)——定制排序
    	 */
    	@Test 
    	public void test3() {
    		//1.开始操作
    		Stream<Employee> stream = list.stream();
    		//2.中间操作
    		//方法7:sorted自然排序
    //		Stream<Employee> sorted = stream.sorted();
    		//方法8:sorted(Comparator) 定制排序
    		Stream<Employee> sorted = stream.sorted((o1,o2)->Double.compare(o2.getSalary(), o1.getSalary()));
    		//3.终止操作
    		sorted.forEach(System.out::println);
    	}
    	//将Employee转换成Stream
    	public static Stream<Object> fromEmployeeToStream(Employee e){
    		return Stream.of(e.getName(),e.getAge(),e.getGender(),e.getSalary());
    	}
    	//案例:获取工资>6000的,第2条——第8条数据,并且去掉重复项,最后打印
    	@Test 
    	public void exec1() {
    		EmployeeData.
    		getData().
    		stream().
    		filter(t->t.getSalary()>6000).
    		skip(1).
    		limit(7).
    		distinct().
    		forEach(System.out::println);
    	}
    	//练习1:获取员工姓名长度大于2的员工的姓名。
    	@Test 
    	public void exec2() {
    		list.stream().map(Employee::getName).filter(s->s.length()>2).forEach(System.out::println);
    	}
    	//练习2:获取员工工资>5000并且年龄<30的员工的工资
    	@Test 
    	public void exec3() {
    		list.stream().filter(e->e.getAge()<30&&e.getSalary()>5000).map(Employee::getSalary).forEach(System.out::println);
    	}
    	//练习3:最老的三个员工的工资
    	@Test 
    	public void exec4() {
    		list.stream().sorted((e1,e2)->Integer.compare(e2.getAge(),e1.getAge())).limit(3).map(Employee::getSalary).forEach(System.out::println);
    	}
    }
    
    

    ###终止操作的相关API
    * allMatch:测试是否全部匹配
    * anyMatch:测试是否至少有一个匹配
    * noneMatch:测试是否所有的都不匹配
    * findFirst:返回第一个
    * findAny:返回并行流中的任意一个
    * count:统计个数
    * max(comparator):返回最大值
    * min(comparator):返回最小值
    * forEach(Consumer):内部迭代(遍历)
    * reduce(BinaryOperator):归约,往往和map搭配使用

    /**
     * 此类用于演示Stream的使用步骤三:终止操作
     * 常见方法:
     * reduce:归约   ★
     * forEach:内部迭代   ★
     * max:求最大值
     * min:求最小值
     * count:统计个数     ★
     * allMatch:检测是否所有元素都匹配指定条件
     * anyMatch:检测是否至少有一个元素匹配指定条件
     * noneMatch:检测是否所有元素都不匹配指定条件
     * findFirst:返回第一个元素
     * findAny:返回任意一个元素
     * collect:将Stream转换成集合对象
     */
    public class TestStreamEnd {
    	List<Employee> list;
    	@Before 
    	public void before() {
    		 list = EmployeeData.getData();
    	}
    	/**
    	 * 匹配与查找
    	 *  allMatch(Predicate p)——检查是否匹配所有元素
    		anyMatch(Predicate p)——检查是否至少匹配一个元素
    		noneMatch(Predicate p)——检查是否没有匹配的元素
    		findFirst——返回第一个元素
    		findAny——返回当前流中的任意元素
    	 */
    	@Test 
    	public void test1() {
    		//1.开始操作:创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作(支持0——n步)
    		//3.终止操作
    		boolean allMatch = stream.anyMatch(e->e.getSalary()>10000);
    		System.out.println(allMatch);
    	}
    	/*
    	 * 统计和迭代
    	 * count
    	 * max
    	 * min
    	 * forEach
    	 */
    	@Test 
    	public void test2() {
    		//1.开始操作:创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作(支持0——n步)
    		//3.终止操作
    		//方法1:count统计
    //		long count = stream.count();
    //		System.out.println(count);
    		//方法2:max求最大值
    		Optional<Employee> max = stream.max((o1,o2)->o1.getAge()-o2.getAge());
    		System.out.println(max);
    	}
    	/*
    	 * 归约
    	 * reduce:反复结合流中的元素
    	 */
    	@Test 
    	public void test3() {
    		//1.开始操作:创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作(支持0——n步)
    		//3.终止操作
    		Optional<Double> sum = stream.map(Employee::getSalary).reduce((t,u)->t+u);
    		System.out.println(sum);
    	}
    	/*
    	 *收集
    	 * collect:收集
    	 */
    	@Test 
    	public void test4() {
    		//1.开始操作:创建Stream对象
    		Stream<Employee> stream = list.stream();
    		//2.中间操作(支持0——n步)
    		//3.终止操作
    		List<Employee> collect = stream.collect(Collectors.toList());
    		System.out.println(collect);
    	}
    	//练习2:员工姓名中包含“马”的员工个数
    	@Test 
    	public void exec2() {
    		Optional<Integer> reduce = list.stream().filter(t->t.getName().contains("马")).map(t->1).reduce((t,u)->t+u);
    		System.out.println(reduce);
    	}
    	//练习:返回最高的工资:
    	@Test 
    	public void exec1() {
    		Optional<Double> max = list.stream().map(Employee::getSalary).max(Double::compare);
    		System.out.println(max);
    	}
    }
    

    JDK8对接口的改进
    JDK8:
    说明:接口中允许出现静态方法和默认方法
    语法:

    静态方法:
    public static 返回类型 方法名(参数列表){
    }
    默认方法:
    public default 返回类型 方法名(参数列表){
    }
    

    使用特点:
    1、静态方法不能被实现类或子接口继承,只能通过所在的接口名调用!
    2、默认方法具备继承性。可以被实现类或子接口继承过去

    解决同名冲突的问题:
    1、类优先原则
    当父类或实现的接口中出现了同名并且已经实现好的方法时,如果子类中没有重写,则默认使用的是父类的方法
    2、当实现的多个接口中出现了同名并且已经实现好的方法时,子类必须重写该方法,否则报错!
    JDK9:
    说明:接口中允许私有方法

    语法:

    private 返回类型 方法名(参数列表){
    	//代码
    }
    

    Optional的特性
    理解:
    Optional实质上是一个容器,里面包装了具体类型的对象。可以避免对象出现空指针异常的现象

    方法:

    of
    ofNullable
    orElse
    

    重复注解
    说明:jdk8支持重复注解
    语法:
    在被修饰的数据上方:
    @注解类名
    @注解类名

    示例:

    public class TestJava8Ann {
    	@MyAnn
    	@MyAnn
    //	@AnnArray({@MyAnn,@MyAnn})
    	String name;
    }
    @Repeatable(AnnArray.class)
    @interface MyAnn{
    	//语法:类型 value() [default 值];
    }
    @interface AnnArray{
    	MyAnn[] value();
    }
    

    ##日期API

    第一代日期:
    Date类
    SimpleDateFormat类

    Date date = new Date();//当前时间
    SimpleDateFormat  sdf = new SimpleDateFormat("yyyy-MM-dd hh::mm::ss");
    String dateString = sdf.format(date);
    
    /**
     * 此类用于演示第一代日期类
     *  Date
     * 	new Date();
     * 	getTime()
     *  SimpleDateFormat
     * 	format
     * 	parse
     */
    public class TestDate1 {
    	//创建Date对象,表示一个时间,精确到毫秒
    	@Test 
    	public void test1() {
    		//代表当前系统时间
    		Date d1 = new Date();
    		System.out.println(d1);
    		//获取距离1970-1-1的毫秒数
    		System.out.println(d1.getTime());
    	}
    	//测试SimpleDateFormat,格式化或解析日期
    	@Test 
    	public void test2() throws ParseException {
    		Date d=new Date();		
    		//1.创建SimpleDateFormat对象
    		//①使用默认的格式 18-8-8 下午4:25
    //		SimpleDateFormat sdf = new SimpleDateFormat();
    		//②使用指定的格式【建议】
    		SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh小时mm分钟ss秒 S毫秒");		
    		//-------------格式化日期(将日期转换成字符串)------------
    		String format = sdf.format(d);
    		System.out.println(format);		
    		//------------解析字符串为日期(将字符串转换成日期)--------		
    		String s = "2018年12月12日 12小时12分钟12秒 12毫秒";
    		Date date = sdf.parse(s);		
    		System.out.println(date);
    	}
    }
    

    第二代日期:
    Calendar抽象类:更侧重于获取和设置日历字段

    		Calendar date = Calendar.getInstance();
    		System.out.println(date);
    		int year = date.get(Calendar.YEAR);
    		int month = date.get(Calendar.MONTH);
    		int day = date.get(Calendar.DAY_OF_MONTH);
    		System.out.println(year+"年"+(month+1)+"月"+day+"日");
    
    /**
     * 此类用于演示第二代日期类
     * Calendar
     */
    public class TestDate2 {
    	@Test 
    	public void test1() {		
    		//1.获取一个Calendar对象
    		Calendar c = Calendar.getInstance();
    //		System.out.println(c);		
    		//2.获取日历字段		
    		System.out.println("年:"+c.get(Calendar.YEAR));
    		System.out.println("月:"+(c.get(Calendar.MONTH)+1));
    		System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));
    		System.out.println("小时:"+c.get(Calendar.HOUR));
    		System.out.println("分钟:"+c.get(Calendar.MINUTE));
    		System.out.println("秒:"+c.get(Calendar.SECOND));		
    		System.out.println("------------------------------------------");
    		//3.设置具体的时间		
    		c.set(2000, 1, 1);
    		System.out.println("年:"+c.get(Calendar.YEAR));
    		System.out.println("月:"+(c.get(Calendar.MONTH)+1));
    		System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH));
    		System.out.println("小时:"+c.get(Calendar.HOUR));
    		System.out.println("分钟:"+c.get(Calendar.MINUTE));
    		System.out.println("秒:"+c.get(Calendar.SECOND));
    	}
    }
    

    第三代日期:

    //1.LocalDate/LocalTime/LocalDateTime————>Calendar
    @Test 
    public void test1() {
    	//①创建日期对象
    	LocalDateTime ldt = LocalDateTime.now();
       //System.out.println(ldt);
    	//②获取日历字段
    	int year = ldt.getYear();
    	int month = ldt.getMonthValue();
    	int day = ldt.getDayOfMonth();
    	int hour = ldt.getHour();
    	int minute = ldt.getMinute();
    	int second = ldt.getSecond();
    	System.out.println(year+"年"+month+"月"+day+"日   "+hour+"小时"+minute+"分钟"+second+"秒");
    }
    //2.Instant————————>Date
    @Test 
    public void test2() {	
    	//①创建Instant对象
    	Instant now = Instant.now();	
    	//②实现Instant和Date之间的转换
    	//Instant——————>Date
    	Date date = Date.from(now);
    	System.out.println(date);
    	//Date——————>Instant
    	Instant instant = date.toInstant();
    	System.out.println(instant);
    }
    //3.DateTimeFormatter——————>SimpleDateFormat
    /*
     * 可以格式化LocalDateTime,也可以格式化Instant
     */
    @Test 
    public void test3() {
    	LocalDateTime ldt = LocalDateTime.now();
    	//①创建DateTimeFormatter对象
    	DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd kk::mm::ss");
    	//②格式化日期(日期——————>字符串)
    	String format = dtf.format(ldt);
    	System.out.println(format);
    	//③解析日期(字符串——>日期)
    	LocalDateTime parse = LocalDateTime.parse("2018-08-08 16::32::21", dtf);
    	System.out.println(parse);
    }
    
  • 相关阅读:
    循序渐进学习栈和队列
    循序渐进学习数据结构之线性表
    2018 noip 备战日志
    2018 noip 考前临死挣扎
    二维前缀和与差分
    noip模板复习
    宽搜总结
    强联通总结
    二分图再次总结
    NOIP 2016 换教室(期望dp)
  • 原文地址:https://www.cnblogs.com/javawxid/p/12812135.html
Copyright © 2011-2022 走看看