java学习笔记——JDK1.8的特性

1. 接口方法

  • JDK1.8之前:接口中的方法必须是抽象方法,其实现类必须实现接口中定义的所有抽象方法。
  • JDK1.8:引入了一种新的机制——接口可以支持声明方法的同时,提供方法的实现。
    主要通过两种方式可以完成这种操作:
    1. 默认方法
    2. 静态方法

1.1 默认方法

JDK1.8中,接口可以定义默认方法
语法:

interface 接口名 {
	default 返回值 方法名(参数列表){
		方法的实现
	}
}

Java中一个类只能继承一个父类,但是可以实现多个接口,由此会出现方法调用优先顺序的问题,如下:

  1. 类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
  1. 类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
  1. 类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表达式格式:() -> {}

  • () 表示参数列表
  • -> 后面跟的是函数主体
  • {} 函数主体

函数式接口中,抽象方法常见的有以下几种:

  1. 函数式接口中,抽象方法无参,无返回值
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);
		};
	}
}
  1. 函数式接口中,抽象方法有参,无返回值
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) -> {};
	}
}
  1. 函数式接口中,抽象方法无参,有返回值
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;
		};
	}
}
  1. 函数式接口中,抽象方法有参有返回值
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. 示例

  1. 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();
		} 
	}
  1. 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;
	}
  1. 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);
		}
	}
  1. 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
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值