JDK1.8特性
1. 接口方法
- JDK1.8之前:接口中的方法必须是抽象方法,其实现类必须实现接口中定义的所有抽象方法。
- JDK1.8:引入了一种新的机制——接口可以支持声明方法的同时,提供方法的实现。
主要通过两种方式可以完成这种操作:- 默认方法
- 静态方法
1.1 默认方法
JDK1.8中,接口可以定义默认方法
语法:
interface 接口名 {
default 返回值 方法名(参数列表){
方法的实现
}
}
Java中一个类只能继承一个父类,但是可以实现多个接口,由此会出现方法调用优先顺序的问题,如下:
- 类A,实现接口B、C,接口B继承接口C;类A中调用接口的默认方法,此时调用到的是接口B的默认方法。(子接口的默认方法优先级高于父接口的默认方法)
interface C {
default void test(){
System.out.println("C");
}
}
interface B extends C{
default void test(){
System.out.println("B");
}
}
class A implements B,C {
public static void main(String[] args) {
A a = new A();
a.test();
}
}
//运行结果:
B
- 类A继承父类B,实现接口C,类B和接口C都有方法test();类A中调用test()方法则会调用类B的test方法。类和接口中的默认方法名字相同,优先调用类中的方法
interface C {
default void test(){
System.out.println("interface C");
}
}
class B {
public void test(){
System.out.println("class B");
}
}
class A extends B implements C {
public static void main(String[] args) {
A a = new A();
a.test();
}
}
//运行结果:
class B
- 类A,实现接口B,接口C,接口B和接口C没有继承关系,两个接口都有默认方法test(),此时A类调用方法test()编译报错。如果需要同时实现A,B接口,那么必须显示覆盖方法test()
interface B {
default void test(){
System.out.println("B");
}
}
interface C {
default void test(){
System.out.println("C");
}
}
class A implements B,C {
public static void main(String[] args) {
A a = new A();
//a.test(); 编译报错
}
}
1.2 静态方法
JDK1.8,接口可以定义静态方法。
定义语法:
interface 接口名 {
static 返回值 方法名(参数列表) {
方法的实现
}
}
访问:
接口名.静态方法名();
注意,接口中的静态方法只能用接口名调用
2. lambda表达式
Lambda表达式,可以用来表示一个函数,它只关注函数的参数列表,函数主体、返回类型,并且可以将此函数作为一个参数,进行传递
在Java中,Lambda表达式还有另一个存在的意义,那就是作为接口的实现类对象。
例:
package com.test.lambda;
public class Test2 {
public static void main(String[] args) {
A a = str -> str;
System.out.println(a.test("hello") + " " + a.test("hello").length());
B b = (str, num) -> str.length() + num;
System.out.println(b.test1("hello", 10));
}
}
interface A{
String test(String str);
}
interface B{
int test1(String str, int num);
}
注:并不是所有接口都可以使用Lambda表达式来实现方法的。
有且只有一个抽象方法的接口,也就是函数式接口才能使用Lambda表达式
函数式接口可以有静态方法和默认方法。
可以给接口添加注解@FunctionalInterface
,用来检查被标注的接口是否是一个函数式接口,如果不是,编译器会报错。
2.1 Lambda表达式语法
Lambda表达式格式:() -> {}
()
表示参数列表->
后面跟的是函数主体{}
函数主体
函数式接口中,抽象方法常见的有以下几种:
- 函数式接口中,抽象方法无参,无返回值
interface A{
void test();
}
public class Test {
public static void main(String[] args) {
A a1 = () -> {};
//方法体中只有一句代码可以省略大括号
A a2 = () -> System.out.println("hello");
//方法体中有多句代码,必须带上大括号
A a3 = () -> {
int a = 1;
int b = 2;
System.out.println(a + b);
};
}
}
- 函数式接口中,抽象方法有参,无返回值
interface A{
//只有一个参数的方法
void test(int a);
}
interface B {
//有多个参数的方法
void test(int a, int b);
}
public class Test {
public static void main(String[] args) {
A a1 = (int a) -> {};
//只有一个参数可以省略小括号
A a2 = a -> {};
A a3 = a -> System.out.println(a);
A a4 = a -> a++;
B b1 = (a, b) -> {};
}
}
- 函数式接口中,抽象方法无参,有返回值
interface A {
int test();
}
public class Test {
public static void main(String[] args) {
A a1 = () -> {return 1};
//如果只有一句代码,大括号和return关键字可以省略
A a2 = () -> 1;
A a3 = () -> {
int num = 10;
return num;
};
}
}
- 函数式接口中,抽象方法有参有返回值
interface A {
int test(int a, int b);
}
public class Test {
public static void main(String[] args) {
A a1 = (a, b) -> a + b;
A a2 = (a, b) -> {
int num = a + b;
return num;
}
}
}
2.2 常用的函数式接口
函数式接口定义在
java.lang.function
包下
其中,常用接口有:
Predicate
Consumer
Function
Supplier
2.2.1 Predicate
该接口定义了一个
test
抽象方法,该方法接收泛型对象,并返回一个boolean类型的结果
该接口中还定义了一些默认方法和静态方法:
and()
== (与 &&)
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
or()
==(或 ||)
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
negate()
==(非 !)
default Predicate<T> negate() {
return (t) -> !test(t);
}
isEqual()
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
2.2.2 Consumer
该接口提供了方法
accept
,该方法可接收泛型对象,无返回值。
JDK1.8中给Collection集合增加了默认方法:forEach
用来遍历集合,他的参数就是Consumer类型
2.2.3 Function
该接口提供了方法
apply
,该方法接收泛型对象,并返回一个泛型对象
2.2.4 Supplier
该接口只提供了一个方法
get
,该方法无参数,返回一个泛型对象。
3. 示例
- java7新增的 trywith-resource的资源自动释放
public void test1() {
//java7之前
FileOutputStream stream = null;
try {
stream = new FileOutputStream("src/a.txt");
} catch (Exception e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void test2() {
//java7新增特性
//自动关流
try(FileOutputStream stream =
new FileOutputStream("src/a.txt");
PrintWriter pw = new PrintWriter("src/a.txt")) {
stream.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
- java8 lambda表达式简化代码
public void test3() {
//java8
//runanble == runable1 == runnable2
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println();
}
};
Runnable runnable2 = () -> {
System.out.println();
};
Runnable runnable3 = System.out::println;
}
- Predicate的使用
/**
* Predicate的使用
*/
public void test1() {
Predicate<Integer> p = t -> true;
boolean test = p.test(1);
System.out.println(test);//输出true
}
public static List<Integer> jisuan(List<Integer> list, Predicate<Integer> p) {
List<Integer> data = new ArrayList<>();
for (Integer integer : list) {
if (p.test(integer)) {
data.add(integer);
}
}
return data;
}
public static void main(String[] args) {
//求偶数
Predicate<Integer> p = t -> t % 2 == 0 ? true : false;
List<Integer> list1 = jisuan(Arrays.asList(1,2,3,4,5,6), p);
for (Integer integer : list1) {
System.out.println(integer);
}
//求奇数
p = t -> t % 2 == 0 ? false : true;
List<Integer> list2 = jisuan(Arrays.asList(1,2,3,4,5,6,7), p);
for (Integer integer : list2) {
System.out.println(integer);
}
//求大于4且小于9的数(and()方法的使用)
Predicate<Integer> p1 = t -> t > 4 ? true : false;
Predicate<Integer> p2 = t -> t < 9 ? true : false;
Predicate<Integer> p3 = p1.and(p2);
List<Integer> list3 = jisuan(Arrays.asList(1,2,3,4,5,6,7), p3);
for (Integer integer : list3) {
System.out.println(integer);
}
}
- Consumer的使用
public class ConsumerTest {
public static void main(String[] args) {
Consumer<String> s = t -> System.out.println(t);
Consumer<String> s1 = System.out::println;
s.accept("aaa");//输出aaa
s1.accept("kkkkk");//输出kkkkk
//----------------------
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.forEach(t -> System.out.print(t));//输出abc
System.out.println();
//list.forEach(System.out::print);//输出abc
}
}