Java8新特性学习笔记

一、接口默认方法和静态方法

接口中可以使用default关键字,来实现方法。

// NumInterface.java
public interface NumInterface
{
   
    // 定义一个抽象方法
	int toDoubleDouble(int number);

    // 默认方法
	default int toDouble(int number) {
   
		return number * 2;
	}
}

接口中实现的默认方法,它的实现类可以直接调用。

// Num.java
public class Num implements NumInterface
{
   
	@Override
	public int toDoubleDouble(int number) {
   
		return toDouble(number) * 2;
	}
}

// Main.java
public static void main(String[] args) {
   
    NumInterface num = new Num(){
   };
    System.out.println(num.toDouble(3)); // 输出6
}

当然,实现类也能重写接口中的默认方法,调用时依据”就近原则“,即实现类如果重写了,就先调用实现类的,否则调用最近接口的。


接口中还能实现静态方法:

// NumInterface.java
public interface NumInterface
{
   
    // 抽象方法
	int toDoubleDouble(int number);

    // 默认方法
	default int toDouble(int number) {
   
		return number * 2;
	}
	
    // 静态方法
	static void sayHello() {
   
		System.out.println("Hello");
	}
}

二、Lambda表达式

例如对一个用户列表进行排序,排序规则是他们的年龄(假设都存在),那么以往的代码是这么写的:

ArrayList<User> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
...

userList.sort(new Comparator<User>()
{
   
	@Override
	public int compare(User o1, User o2) {
   
		return o1.getAge() - o2.getAge();
	}
});

上面的代码传入了一个匿名内部类,来实现Comparator接口中的compare方法。

现在就能简化这一个操作。

userList.sort((User a, User b) -> {
   
	return a.getAge() - b.getAge();
});

对于只包含一行方法的代码块,我们可以省略大括号和return

甚至能更加简化:

userList.sort((a, b) -> a.getAge() - b.getAge());

使用Lambda表达式的前提是,接口必须为函数式接口

三、函数式接口

函数式接口,就是只包含一个需要被实现的抽象方法的接口。

也就是说:接口中可以定义其他的方法,比如默认方法、抽象方法、甚至是equalstoString这些不需要被实现的方法(Object类中实现了),只需要保证只有一个抽象方法需要被实现就行。

为了保证一个接口明确的被定义为一个函数式接口,可以在接口上添加注解:@FunctionalInterface,如果接口中添加了其他的抽象方法,就会报错。

// NumInterface.java
@FunctionalInterface
public interface NumInterface
{
   
    // 定义一个抽象方法
	int toDoubleDouble(int number);

    // 默认方法
	default int toDouble(int number) {
   
		return number * 2;
	}
}

上面的代码,即使去掉 @FunctionalInterface 也是好使的,它仅仅是一种约束而已。

四、方法引用

String::compareToIgnoreCase 这种“对象/类名 + 双冒号 + 方法名”格式就是方法引用。

所谓方法引用,是指如果某个方法签名和接口的恰好一致,就可以直接传入方法引用。

例如这一段代码:

public static void main(String[] args) {
   
	String[] array = new String[] {
    "Apple", "Orange", "Banana", "Lemon" };
	Arrays.sort(array, Main::cmp);
	System.out.println(String.join(", ", array));
}

static int cmp(String s1, String s2) {
   
    return s1.compareTo(s2);
}

本来Arrays.sort()中的第二个参数是传入的int compare(String, String)这种类型的,而cmp方法的参数列表、返回类型和需求一致。因此,两者的方法签名一致,可以直接把方法名作为lambda表达式传入:

Arrays.sort(array, Main::cmp);

当然,里面也可传入String::compareTo,而compareTo方法中只有一个参数。这是因为方法参数中含有一个隐藏的this,每次调用compareTo时,实际上是调用public static int compareTo(this, String o),所以也是可行的。


方法引用的四个种类:

  1. 静态方法引用

格式:类名::静态方法名

上面的例子Main:cmp就是静态方法引用,和静态方法调用相比,就是把.换成了::

例如:

Math::pow 等效于 (x, y) -> Math.pow(x, y)

String::valueOf 等效于 (x) -> String.valueOf(x)

  1. 实例方法引用

格式:实例名::实例中的方法名

例如:

public static void main(String[] args) {
   
    List<String> list = Arrays.asList("hello", "kitty");
    list.forEach(new Main()::printWithSpace);
}

private void printWithSpace(String s) {
   
    for (int i = 0 ; i < s.length() ; i++) {
   
        System.out.print(s.charAt(i) + " ");
    }
}
  1. 实例的超类方法引用

格式:super::超类中的方法名

这里的super指的是当前类的父类。

例如:

public
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值