独到理解_Java1.8新特性

jdk1.8新特性

一、知识点

1. Lambda表达式

1.1 介绍

Lambda表达式是一种没有名字的函数,也可称为闭包,是Java 8 发布的最重要新特性。
本质上是一段匿名内部类,也可以是一段可以传递的代码。
还有叫箭头函数的…

  • 闭包

闭包就是能够读取其他函数内部变量的函数,比如在java中,方法内部的局部变量只能在方法内部使用,所以闭包可以理解为定义在一个函数内部的函数
闭包的本质就是将函数内部和函数外部链接起来的桥梁

1.2 特点

允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
使用 Lambda 表达式可以使代码变的更加简洁紧凑。

1.3 应用场景

列表迭代

Map映射

Reduce聚合

代替一个不想命名的函数或是类,该函数或类往往并不复杂。

想尽量缩短代码量的各个场景均可以

1.4 代码实现
1.4.1 具体语法
  1. (parameters) -> expression

  2. (parameters) ->{ statements; }

1.4.2 语法特点

可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值

如果只有一条语句,并且是返回值语句,就可以不写return 不写 {}
如果写上{} 就必须写return 和 ;
如果有 多条语句,必须写{} return 和 ; 也必须写

  • 案例说明-简单

// 1. 不需要参数,返回值为 5
() -> 5

// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2*x

// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y

// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
1.4.3 集合遍历

实例 :

package _01_Lambda;

import java.util.Arrays;
import java.util.List;

/**
 * 列表迭代
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class Lambda_01 {

	public static void main(String[] args) {
		String[] arr = { "one", "two", "three" };
		List<String> list = Arrays.asList(arr);

		// jdk1.7 - 老版写法
		for (String string : list) {
			System.out.println(string);
		}
		System.out.println("0---");

		// jdk1.8 - 新版写法
		// 也有叫箭头函数
		list.forEach(x -> {
			System.out.println(x);
		});

//		one
//		two
//		three

		// 就类似于这种写法,相当于自己创建了一个方法,然后遍历调用这个方法
		// 把集合中每个元素作为参数传递进去,并打印参数
		for (String string : list) {
			m1(string);
		}
	}

	public static void m1(String x) {
		System.out.println(x);
	}
}

1.4.3 集合排序

实例 :

package _01_Lambda;

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * 列表排序
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class Lambda_02 {

	public static void main(String[] args) {
		Integer[] arr = { 4, 6, 1, 6, 7 };
		List<Integer> list = Arrays.asList(arr);

		System.out.println(list);

		list.sort(new Comparator<Integer>() {

			@Override
			public int compare(Integer o1, Integer o2) {
				return o1 - o2;
			}
		});
		System.out.println(list);

		Integer[] arr1 = { 4, 6, 5, 9, 8 };
		list = Arrays.asList(arr1);
		System.out.println(list);
		// 如果只有一条语句,并且是返回值语句,就可以不写 return 不写 {}
		// 如果写上 {} 就必须写上 return 和 ;
		// 如果有多条语句,必须写 {} return 和 ; 也必须写
		list.sort((x, y) -> {
			return x - y;
		});

//		[4, 5, 6, 8, 9]

		System.out.println(list);
	}

}

2. 函数式接口

2.1 介绍

英文称为Functional Interface

其本质是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

核心目标是为了给Lambda表达式的使用提供更好的支持,进一步达到函数式编程的目标,可通过运用函数式编程极大地提高编程效率。

其可以被隐式转换为 lambda 表达式。

2.2 特点

函数式接口是仅制定一个抽象方法的接口

可以包含一个或多个静态或默认方法

专用注解即@FunctionalInterface 检查它是否是一个函数式接口,也可不添加该注解
如果有两个或以上 抽象方法,就不能当成函数式接口去使用,也不能添加@FunctionalInterface这个注解
如果只有一个抽象方法,那么@FunctionalInterface注解 加不加 都可以当做函数式接口去使用

  • 回调函数

简单来说就是回调函数,方法的参数是一个方法,在这个方法中对传递的方法进行调用

2.3 应用场景

想通过函数式编程,提高编程效率的各种场景均可。

2.4 代码实现
2.4.1 无参情况
package _02_FunInterface;

/**
 * 函数式接口 - 无参
 * 
 * @author lenovo
 * @date 2020年7月28日 @time 上午9:20:50
 */
public class _01_FunInterface {
	// 自定义静态方法,接收接口对象
	public static void call(MyFunctionInter func) {
		// 调用接口内的成员方法
		func.printMessage();
	}

	public static void main(String[] args) {
		// 1.8 之前写法
		// 第一种 子实现类
		Test t = new Test();
		call(t);

		// 第二种 匿名内部类
		call(new MyFunctionInter() {

			@Override
			public void printMessage() {
				// TODO Auto-generated method stub
				System.out.println("匿名内部类的方式");
			}
		});

		// 1.8 新特性写法

		// 第一种调用 : 直接调用自定义的 call 方法,传入箭头函数
		// 这个箭头函数,就等于是实现类中实现的这个抽象方法,只不过不用写实现类
		// 并且也比匿名内部类的写法简单
		call(() -> {
			System.out.println("lammbda写法");
		});

		// 第二种调用 : 先创建函数对象,类似实现接口的内部类对象
		MyFunctionInter inter = () -> {
			System.out.println("保存为函数对象变量,再调用");
		};
		// 传入自定义方法
		call(inter);

		// 调用实现的这个方法
		inter.printMessage();
	}

}

//函数式接口,只能由一个抽象方法,但是可以有默认方法
@FunctionalInterface
interface MyFunctionInter {
	void printMessage();
}

//实现类
class Test implements MyFunctionInter {

	@Override
	public void printMessage() {
		System.out.println("实现类的方式");
	}

}
2.4.2 有参情况
package _02_FunInterface;

/**
 * 函数式接口 - 有参
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _02_FunInterface {
	// 自定义静态方法,接收接口对象
	public static void call(MyFunctionInter_02 func, String msg) {
		// 调用接口内的成员方法
		func.printMessage(msg);
	}

	public static void main(String[] args) {
		// 1.8新特性写法
		// 第一种调用 : 直接调用自定义的 call 方法,传入箭头函数
		call((str) -> {
			System.out.println(str);
		}, "参数1");

		// 第二种调用 : 先创建函数对象,类似实现类接口的内部类对象
		MyFunctionInter_02 inter = (str) -> {
			System.out.println(str);
		};
		// 传入自定义方法
		call(inter, "参数2");

		// 调用实现的这个方法
		inter.printMessage("参数3");

//		参数1
//		参数2
//		参数3

	}

}

//函数式接口,只能由一个抽象方法,但是可以有默认方法
@FunctionalInterface
interface MyFunctionInter_02 {
	void printMessage(String msg);
}

2.5 JDK自带常用的函数式接口
2.5.1 SUPPLIER接口

Supplier接口 代表结果供应商,所以有返回值,可以获取数据
有一个get方法,用于获取数据

package _02_FunInterface;

import java.util.function.Supplier;

/**
 * Supplier 接口,代表供应商,可以获取数据
 * 
 * 有一个 get 方法
 * 
 * 没有参数 有返回值
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _03_JDKOwn_01 {
	public static String getResult(Supplier<String> function) {
		return function.get();
	}

	public static void main(String[] args) {
		String before = "      李 四     ";
		String after = "      干得漂亮     ";
		getResult(new Supplier<String>() {

			@Override
			public String get() {
				// TODO Auto-generated method stub
				return before + after;
			}
		});

		String result = getResult(() -> before.trim() + after.trim());
		System.out.println(result);

//		李 四干得漂亮

	}

}

2.5.2 CONSUMER接口

Consumer接口 消费者接口所以不需要返回值

有一个accept(T)方法,用于执行消费操作,可以对给定的参数T 做任意操作

package _02_FunInterface;

import java.util.function.Consumer;

/**
 * Consumer 接口有一个 accept(T) 方法,没有返回值,用于执行消费操作
 * 
 * 有参数 没有返回值
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _04_JDKOwn_02 {

	public static void consumeResult(Consumer<String> function, String msg) {
		function.accept(msg);
	}

	public static void main(String[] args) {
		consumeResult(new Consumer<String>() {

			@Override
			public void accept(String t) {
				System.out.println(t);
			}
		}, "00000000");

		// msg 是自己写的,你想叫什么就叫什么
		consumeResult(msg -> {
			System.out.println(msg);
		}, "11111");

//		00000000
//		11111
	}

}

2.5.3 FUNCTION<T,R>接口

Function<T,R>接口 表示接收一个参数并产生结果的函数
顾名思义,是函数操作的

有一个R apply(T)方法,Function中没有具体的操作,具体的操作需要我们去为它指定,因此apply具体返回的结果取决于传入的lambda表达式

package _02_FunInterface;

import java.util.function.Function;

/**
 * Function 表示接受一个参数,并且产生结果
 * 
 * 有参 有返回值
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _05_JDKOwn_03 {

	// Function<参数,返回值>
	public static void converType(Function<String, Integer> function, String str) {
		int num = function.apply(str);
		System.out.println(num);
	}

	public static void main(String[] args) {
		converType(new Function<String, Integer>() {

			@Override
			public Integer apply(String t) {
				int num = Integer.parseInt(t);
				return num;
			}
		}, "456");

//		456

		converType((s) -> {
			int num = Integer.parseInt(s);
			return num;
		}, "789");

//		789

	}

}

2.5.4 PREDICATE接口

Predicate接口 断言接口
就是做一些判断,返回值为boolean

有一个boolean test(T)方法,用于校验传入数据是否符合判断条件,返回boolean类型

package _02_FunInterface;

import java.util.function.Predicate;

/**
 * Predicate 断言
 * 
 * boolean test(T) 用于校验传入的数据是否符合条件
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _06_JDKOwn_04 {

	public static void call(Predicate<String> predicate, String isOk) {
		boolean flag = predicate.test(isOk);
		System.out.println(flag);
	}

	public static void main(String[] args) {
		call(new Predicate<String>() {

			@Override
			public boolean test(String t) {
				if (t.equals("OK")) {
					return true;
				}
				return false;
			}
		}, "asdf");

		call((t) -> {
			if (t.equalsIgnoreCase("asdf")) {
				// equalsIgnoreCase 不区分大小写的比较
				return true;
			}
			return false;

		}, "asdf");

//		false
//		true

	}

}

3. 方法引用和构造器调用

3.1概念说明

Lambda表达式的另外一种表现形式,提高方法复用率和灵活性。

3.2 特点

更简单、代码量更少、复用性、扩展性更高。

3.3 应用场景

若Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用。

不需要再复写已有API的Lambda的实现。

3.4 代码实现
3.4.1 方法引用

方法引用-3种形式

3.4.1.1 对象的引用 :: 实例方法名
package _03_FunCall;

import java.util.function.Supplier;

/**
 * 对象引用 :: 成员方法名
 * 
 * @author lenovo
 * @date 2020年7月27日
 */
public class _01_FunCall {

	public static void main(String[] args) {
		Integer intObj = new Integer(100);

		// 正常写法
//		System.out.println(intObj.toString());
//		100

		// lambda 写法
		Supplier<String> supplier = () -> intObj.toString();
		System.out.println(supplier);
		System.out.println(supplier.get());

		// 方法引用写法
		Supplier<String> supplier1 = intObj::toString;
		System.out.println(supplier1.get());
	}

}

3.4.1.2 类名 :: 静态方法名
package _03_FunCall;

import java.util.function.BiFunction;

public class _02_FunCall {

	public static void main(String[] args) {
		// 前两位是参数,第三位是返回值类型
		BiFunction<Integer, Integer, Integer> bi = (x, y) -> Integer.max(x, y);
		System.out.println(bi.apply(10, 111));

//		111

		BiFunction<Integer, Integer, Integer> bi1 = Integer::max;
		System.out.println(bi1.apply(22, 33));

//		33
	}

}

3.4.1.3 类名 :: 实例方法名
package _03_FunCall;

import java.util.function.BiPredicate;

public class _03_FunCall {

	public static void main(String[] args) {
		// 两个都是参数并且 Predicate 是断言,所以这个方法就是用来比较两个参数是否相等
		BiPredicate<String, String> predicate = (x, y) -> x.equals(y);
		System.out.println(predicate.test("abc", "abc"));

		// 用第一个参数 调用指定的方法,把第二个参数传递进去
		// 所以 :: 前面的类型要和 第一个参数的类型一致
		@SuppressWarnings("unlikely-arg-type")
		BiPredicate<Integer, String> predicate1 = Integer::equals;
		System.out.println(predicate1.test(123, "123"));

//		true
//		false

	}

}

class A implements BiPredicate<String, String> {

	@Override
	public boolean test(String t, String u) {
		return t.equals(u);
	}

}
3.4.3 构造器调用
package _03_FunCall;

import java.util.function.Function;
import java.util.function.Supplier;

public class _04_ConstructorCall {

	public static void main(String[] args) {
		// 无参构造

		// lambda 写法
		Supplier<Object> objSupplier = () -> new Object();
		System.out.println(objSupplier);
		System.out.println(objSupplier.get());

		// 方法引用写法
		Supplier<Object> s1 = Object::new;
		System.out.println(s1.get());

//		java.lang.Object@1fb3ebeb
//		java.lang.Object@816f27d

		// 有参构造

		// lambda 写法
		Function<String, Integer> function = (x) -> new Integer(x);
		System.out.println(function.apply("123"));

		// 方法引用写法
		Function<String, Integer> function1 = Integer::new;
		System.out.println(function1.apply("123"));

//		123
//		123

	}

}

3.4.4 数组调用
package _03_FunCall;

import java.util.function.Function;

public class _05_ArrayCall {

	public static void main(String[] args) {
		// lambda
		Function<Integer, int[]> fun = (n) -> new int[n];
		int[] arr1 = fun.apply(10);
		System.out.println(arr1.length);

//		10

		// 数组引用
		fun = int[]::new;
		int[] arr2 = fun.apply(5);
		System.out.println(arr2.length);

//		5

	}
}

4. Stream API

4.1 概念说明

数据渠道、管道,用于操作数据源(集合、数组等)所生成的元素序列。

集合讲的是数据,流讲的是计算

即一组用来处理数组,集合的API。

4.2 特点

Stream 不是数据结构,没有内部存储,自己不会存储元素。

Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

不支持索引访问。

延迟计算

支持并行

很容易生成数据或集合

支持过滤,查找,转换,汇总,聚合等操作。

4.3 应用场景

流式计算处理,需要延迟计算、更方便的并行计算

更灵活、简洁的集合处理方式场景

4.4 代码实现
4.4.1 运行机制说明

Stream分为源source,中间操作,终止操作。

流的源可以是一个数组,集合,生成器方法,I/O通道等等。

一个流可以有零个或多个中间操作,每一个中间操作都会返回一个新的流,供下一个操作使用,一个流只会有一个终止操作。

中间操作也称为转换算子-transformation

Stream只有遇到终止操作,它的数据源会开始执行遍历操作。

终止操作也称为动作算子-action
因为动作算子的返回值不再是 stream,所以这个计算就终止了
只有碰到动作算子的时候,才会真正的计算

4.4.2 代码实现
4.4.2.1 生成stream流的5种方式说明
package _04_Stream;

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

public class _01_Stream {

	public static void main(String[] args) {
		// 1.通过数组 Stream.of
		// Stream 类中的静态方法
		String[] strings = { "q", "w", "e", "r", "d", "f" };
		Stream<String> stream1 = Stream.of(strings);
		Stream<String> stream3 = Arrays.stream(strings);

		// 2.通过集合
		// 集合提供的 stream()方法或parallelStream()
		List<String> string2 = Arrays.asList(strings);
		Stream<String> stream2 = string2.stream();

		// 3.通过 Stream.generate 方法创建
		// 这是一个无限流(无限大),通过这种方式创建的流,在操作的时候,最好使用 limit 进行最大数量限制

		// generate 的参数是 Supplier,只有一个 get 方法,是无参有返回值的,所以 ()->xxxx
		Stream<Integer> generate = Stream.generate(() -> 111);
		// 通过 limit 限制最多元素个数为 3 个
		generate.limit(3).forEach(x -> System.out.println(x));

		System.out.println("1111");

		// 4.通过Stream.iterate 方法来创建
		// 这是一个有序无限流(无限大),通过这种方式创建的流,在操作的时候,最好使用 limit 进行最大数量限制

		// iterate() 第一个是起始值,第二个参数是 UnaryOperator,继承了 Function ,所以是有参有返回值
		// 1 表示起始值,x+2等于是步长,就类似于一个死循环,起始值是1,步长是2
		Stream<Integer> iterate = Stream.iterate(1, x -> x + 2);
		// 通过 limit 限制最多元素个数为 10 个
		iterate.limit(10).forEach(x -> System.out.println(x));

		// 5.已有类的 Stream 源生成 API
		String str = "abc";
		IntStream chars = str.chars();
		// 97,98,99
		chars.forEach(x -> System.out.println(x));
	}

}

4.4.2.2 常用转换算子

常用转换算子 filter,distinct,map,limit,skip,flatMap等

filter : 对元素进行过滤筛选,不符合的就不要了

distinct : 去掉重复的元素

skip : 跳过多少元素

limit : 取一个集合的前几条数据

map :
可以理解是在遍历集合的过程中,对元素进行操作,比如判断集合元素是否是a 返回boolean
因为 map的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加 –

flatMap : 解决一个字符串数组 返回单一的字符串使用flatMap
本来集合中有两个数组,可以通过flatMap 把数组中的每一个元素都放到集合中,然后把数组去掉

注意只用此算子是不会真正进行计算的,只有后边调用动作算子才会真正计算。

package _04_Stream;

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

/**
 * 转换算子
 * 
 * filter : 对元素进行过滤筛选,不符合条件的就不要了
 * 
 * skip : 跳过一个元素,原来是 abca 现在是 bca
 * 
 * @author lenovo
 * @date 2020年7月28日 @time 上午11:48:55
 */
public class _02_Stream {

	public static void main(String[] args) {
		List<String> strings = Arrays.asList("a", "b", "c", "a");
		Stream<String> stream = strings.stream();
		System.out.println(strings);

		/**
		 * filter : 对元素进行过滤筛选,不符合条件的就不要了
		 */
		// collect 把stream 转换为集合,属于动作算子,因为不使用动作算子,这些转换算子是不会执行的
		List<String> value = stream.filter(x -> x.equals("a")).collect(Collectors.toList());
		// 只有a
		System.out.println(value);

		// 使用之后,必须重新生成 stream ,不能使用原来的stream
		// 因为转换算子的返回值是一个新的 stream,所以可以链式调用,因为新的stream 还没有进行过操作
		// 否则报错, java.lang.IllegalStateException: stream has already been operated
		// uponor closed
		// 意思是流已操作或关闭

		stream = strings.stream();

		/**
		 * skip : 跳过 1 个元素,原来是 abca 现在是 bca
		 */
		value = stream.skip(1).collect(Collectors.toList());
		System.out.println(value);

		/**
		 * map : 在遍历集合的时候,对元素的操作,比如判断是否是 a ,返回 boolean 类型
		 * 
		 * 因为 map 的返回值,就是新集合中的元素,所以也可以在遍历的时候对集合的数据进行更改,比如都加 --
		 */
		// 使用之后,必须重新生成stream
		stream = strings.stream();
		List<Boolean> value1 = stream.map(x -> x.equals("a")).collect(Collectors.toList());
		System.out.println(value1);
//		[true, false, false, true]

		stream = strings.stream();
		value = stream.map(x -> x + "--").collect(Collectors.toList());
		System.out.println(value);

		/**
		 * distinct : 去掉重复
		 */
		// 使用之前,必须重新生成 stream
		stream = strings.stream();
		value = stream.distinct().collect(Collectors.toList());
		System.out.println(value);

		/**
		 * limit : 取一个集合的前几条数据
		 */
		// 使用之前,必须重新生成stream
		stream = strings.stream();
		value = stream.limit(2).collect(Collectors.toList());
		System.out.println(value);
	}

}

4.4.2.3 常用动作算子
循环 forEach

计算 min、max、count、average

匹配 anyMatch、allMatch、noneMatch、findFirst、findAny

汇聚 reduce

收集器 collect

package _04_Stream;

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

/**
 * 动作算子
 * 
 * forEach 循环
 * 
 * min,max,count,average 计算
 * 
 * 匹配 anyMath,allMath
 * 
 * 收集器 collect
 * 
 * @author lenovo
 * @date 2020年7月28日 @time 下午3:43:21
 */
public class _03_Stream {

	public static void main(String[] args) {
		List<String> strings = Arrays.asList("a", "b", "c");

		Stream<String> stream = strings.stream();
		// 测试 forEach
		stream.filter(x -> x.equals("a")).forEach(x -> System.out.println(x));

		// a

		// 测试count
		stream = strings.stream();
//		a

		// 统计有多少元素
		// 如果只是想查看有多少元素,可以直接调用集合的在size()更加简单
		// 一般动作算子和转换算子 一起使用,才能体现出优势
		long count = stream.count();
		System.out.println(count);
//		3

		// 统计集合中有多少a,正常写法,就是循环遍历,然后定义一个变量累加,最终变量的值就是a 的个数
		// 使用转换算子和动作算子一起使用,更加简单
		stream = strings.stream();
		// 结合转换算子一起使用,统计有几个 a 1
		count = stream.filter(x -> x.equals("a")).count();
		System.out.println(count);

		// 测试 collect
		stream = strings.stream();
		List<String> list = stream.map(x -> x + 1).collect(Collectors.toList());
		System.out.println(list);
	}

}

5. 接口中的默认方法和静态方法

5.1 概念说明

1.8之前接口中只能定义public static final的变量和public abstract修饰的抽象方法。
1.8及以后版本,不仅兼容1.8以前的,并新增了默认方法定义和静态方法定义的功能。

即default方法和static方法。
让接口更灵活、更多变,更能够适应现实开发需要。

5.2 特点

默认方法

可以被重写,也可以不重写。如果重写的话,就按实现类的方法来执行。

调用的时候必须是实例化对象调用。

静态方法

跟之前的普通类的静态方法大体相同

唯一不同的是不能通过接口的实现类的对象来调用,必须是类.静态方法的方式。

5.3 应用场景

默认方法

是为了解决之前版本接口升级导致的大批实现类的强制重写方法升级的问题。

涉及到接口升级的场景可以多用,从而提高了程序的扩展性、可维护性。

静态方法

跟默认方法为类似,也是为了解决接口升级的问题,默认方法解决了接口方法增加后其子类不必要全部重写的问题,静态方法解决了一次编写静态方法所有接口及其子类通用的问题,跟lambda表达式并用效果更加,进一步提高了程序扩展性和可维护性。

允许在已有的接口中添加静态方法,接口的静态方法属于接口本身,不被继承,也需要提供方法的静态实现后,子类才可以调用。

5.4 代码实现

5.4.1 默认方法
package _05_Interface;

/**
 * 默认方法
 * 
 * @author lenovo
 * @date 2020年7月28日 @time 下午3:53:11
 */
public class _01_Interface {

	public static void main(String[] args) {
		MyInter inter = new MyInterlmpl();
		System.out.println(inter.add(2, 1));
		inter.printMessage();
//		3
//		子类覆写的默认方法

		MyInter inter1 = (x, y) -> x + y;
		System.out.println(inter.add(2, 3));
		inter1.printMessage();
//		5
//		接口中的默认方法

	}

}

interface MyInter {
	int add(int i, int j);

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

class MyInterlmpl implements MyInter {

	@Override
	public int add(int i, int j) {
		// TODO Auto-generated method stub
		return i + j;
	}

	@Override
	public void printMessage() {
		// 直接使用 super 是找继承的父类
		// 那么如何调用接口中的默认方法呢? 使用接口名.super.方法();
		// MyInter.super.printMessage();

		System.out.println("子类覆写的默认方法");
	}
}
5.4.2 静态方法案例-1-一般情况

类名调用就行,各是各的,互不影响

package _05_Interface;

/**
 * 静态方法 一般情况
 * 
 * 类名调用即可,相互不影响
 * 
 * @author lenovo
 * @date 2020年7月28日 @time 下午4:01:05
 */
public class _02_Interface {

	public static void main(String[] args) {
		Person.run();
		Man.run();

//		人都可以跑
//		人后可以跑,男人跑的更快
		// 两种方法都行,接口直接调用静态方法,也可以用实现类
	}

}

interface Person {
	public static void run() {
		System.out.println("人都可以跑");
	}
}

class Man implements Person {
	public static void run() {
		System.out.println("人后可以跑,男人跑的更快");
	}
}
5.4.3 静态方法案例-2-高级使用

类名调用就行,各是各的,互不影响

package _05_Interface;

import java.util.function.Supplier;

public class _03_Interface {

	public static void main(String[] args) {
		Person_01 m1 = PersonFactory.create(Man_01::new);
		m1.say();
//		人们都会说话,男人说话更粗糙

	}

}

interface PersonFactory {
	public static Person_01 create(Supplier<Person_01> supplier) {
		return supplier.get();
	}
}

interface Person_01 {
	default void say() {
		System.out.println("人都会说话");
	}

	public static void run() {
		System.out.println("人都可以跑");
	}
}

class Man_01 implements Person_01 {
	@Override
	public void say() {
		// 直接使用 super 是找继承的父类
		// 如何调用接口中的默认方呢? 使用接口名.super.fangfa()
//		Person_01.super.say();
		System.out.println("人们都会说话,男人说话更粗糙");
	}

	public static void run() {
		System.out.println("人都可以跑,男人跑的更快");
	}
}

6. 新时间日期API

6.1 概念说明

新增了专用于处理时间日期API类,包括本地化、日期格式化等方面。

6.2 特点

对解决各类常见问题,更方便、更简单、更高效

6.3 应用场景

可以替换之前用Date类的各种功能操作,编程效率更高。

6.4 代码实现
6.4.1 新增核心类

均在java.time包下
LocalDate
LocalTime
LocalDateTime
DateTimeFormatter:解析和格式化日期或时间的类 由日期时间的格式组成的 类
Instant:时间戳类
Duration:间隔计算,可以计算两个时间的间隔
Period:间隔计算,计算两个日期的间隔
ZonedDate ZonedTime ZonedDateTime:时区处理类,均带有当前系统的默认时区

6.4.2 案例演示
package _06_Time;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class _01_Time {

	public static void main(String[] args) {
		/**
		 * 日期相关
		 */
		// 获取当前日期 yyyy-MM-dd
		LocalDate now1 = LocalDate.now();
		System.out.println(now1);

		// 获取年
		System.out.println(now1.getYear());

		// 月
		System.out.println(now1.getMonthValue());

		// 一年中的第几天
		System.out.println(now1.getDayOfYear());

		// 日(月中第几天)
		System.out.println(now1.getDayOfMonth());

		// 星期
		System.out.println(now1.getDayOfWeek());

		/**
		 * 时间相关
		 */
		// 获取时间 HH:mm:ss.SSS
		LocalTime now2 = LocalTime.now();
//		16:30:02.967
		System.out.println(now2);

		LocalDateTime now3 = LocalDateTime.now();
		System.out.println(now3);

		/**
		 * 格式化
		 */

		DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH点mm分ss秒SSS毫秒");
		String format = now3.format(formatter);

		System.out.println(format);
//		2020年07月28日 16点33分02秒845毫秒

		/**
		 * 判断日期是另一个日期之前或之后
		 */
		// 指定一个时间,转换的 LocalDate 对象
		// now()获取当前系统时间
		// of是指时间
		LocalDate of = LocalDate.of(2020, 7, 28);

		// 判断 now1 是否在 of 之后
		boolean after = now1.isAfter(of);
		System.out.println(after);
//		false

		// 判断now1是否在 of 之前
		boolean before = now1.isBefore(of);
		System.out.println(before);
//		false
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值